Подтвердить что ты не робот

Получить элемент управления Windows Forms по имени в С#

У меня есть ToolStripMenuItem, называемый "myMenu". Как я могу получить доступ к этому так:

/* Normally, I would do: */
this.myMenu... etc.

/* But how do I access it like this: */
String name = myMenu;
this.name...

Это связано с тем, что я динамически генерирую ToolStripMenuItems из файла XML и нуждаюсь в ссылке на элементы меню их динамически сгенерированными именами.

4b9b3361

Ответ 2

string name = "the_name_you_know";

Control ctn = this.Controls[name];

ctn.Text = "Example...";

Ответ 3

Control GetControlByName(string Name)
{
    foreach(Control c in this.Controls)
        if(c.Name == Name)
            return c;

    return null;
}

Не обращайте на это внимания, я изобретаю колеса.

Ответ 4

this.Controls.Find(name, searchAllChildren) не находит ToolStripItem, потому что ToolStripItem не является элементом управления

  using SWF = System.Windows.Forms;
  using NUF = NUnit.Framework;
  namespace workshop.findControlTest {
     [NUF.TestFixture]
     public class FormTest {
        [NUF.Test]public void Find_menu() {
           // == prepare ==
           var fileTool = new SWF.ToolStripMenuItem();
           fileTool.Name = "fileTool";
           fileTool.Text = "File";

           var menuStrip = new SWF.MenuStrip();
           menuStrip.Items.Add(fileTool);

           var form = new SWF.Form();
           form.Controls.Add(menuStrip);

           // == execute ==
           var ctrl = form.Controls.Find("fileTool", true);

           // == not found! ==
           NUF.Assert.That(ctrl.Length, NUF.Is.EqualTo(0)); 
        }
     }
  }

Ответ 5

Предполагая, что у вас есть объект menuStrip, и меню находится только на одном уровне, используйте:

ToolStripMenuItem item = menuStrip.Items
    .OfType<ToolStripMenuItem>()
    .SelectMany(it => it.DropDownItems.OfType<ToolStripMenuItem>())
    .SingleOrDefault(n => n.Name == "MyMenu");

Для более глубоких уровней меню добавьте еще несколько операторов SelectMany в оператор.

если вы хотите искать все пункты меню в полосе, используйте

ToolStripMenuItem item = menuStrip.Items
    .Find("MyMenu",true)
    .OfType<ToolStripMenuItem>()
    .Single();

Однако убедитесь, что у каждого меню есть другое имя, чтобы избежать исключения, вызванного дубликатами ключа.

Чтобы избежать исключений, вы можете использовать FirstOrDefault вместо SingleOrDefault/Single или просто вернуть последовательность, если у вас может быть дубликат Name.

Ответ 6

Поскольку вы генерируете их динамически, сохраняйте карту между строкой и пунктом меню, что позволит быстро найти.

// in class scope
private readonly Dictionary<string, ToolStripMenuItem> _menuItemsByName = new Dictionary<string, ToolStripMenuItem>();

// in your method creating items
ToolStripMenuItem createdItem = ...
_menuItemsByName.Add("<name here>", createdItem);

// to access it
ToolStripMenuItem menuItem = _menuItemsByName["<name here>"];

Ответ 7

this.Controls["name"];

Это фактический код, который выполняется:

public virtual Control this[string key]
{
    get
    {
        if (!string.IsNullOrEmpty(key))
        {
            int index = this.IndexOfKey(key);
            if (this.IsValidIndex(index))
            {
                return this[index];
            }
        }
        return null;
    }
}

против

public Control[] Find(string key, bool searchAllChildren)
{
    if (string.IsNullOrEmpty(key))
    {
        throw new ArgumentNullException("key", SR.GetString("FindKeyMayNotBeEmptyOrNull"));
    }
    ArrayList list = this.FindInternal(key, searchAllChildren, this, new ArrayList());
    Control[] array = new Control[list.Count];
    list.CopyTo(array, 0);
    return array;
}

private ArrayList FindInternal(string key, bool searchAllChildren, Control.ControlCollection controlsToLookIn, ArrayList foundControls)
{
    if ((controlsToLookIn == null) || (foundControls == null))
    {
        return null;
    }
    try
    {
        for (int i = 0; i < controlsToLookIn.Count; i++)
        {
            if ((controlsToLookIn[i] != null) && WindowsFormsUtils.SafeCompareStrings(controlsToLookIn[i].Name, key, true))
            {
                foundControls.Add(controlsToLookIn[i]);
            }
        }
        if (!searchAllChildren)
        {
            return foundControls;
        }
        for (int j = 0; j < controlsToLookIn.Count; j++)
        {
            if (((controlsToLookIn[j] != null) && (controlsToLookIn[j].Controls != null)) && (controlsToLookIn[j].Controls.Count > 0))
            {
                foundControls = this.FindInternal(key, searchAllChildren, controlsToLookIn[j].Controls, foundControls);
            }
        }
    }
    catch (Exception exception)
    {
        if (ClientUtils.IsSecurityOrCriticalException(exception))
        {
            throw;
        }
    }
    return foundControls;
}

Ответ 8

Предполагая, что у вас есть Windows.Form Form1 в качестве родительской формы, которая владеет созданным вами меню. Один из атрибутов формы называется .Menu. Если меню было создано программно, оно должно быть одинаковым, и оно будет распознано как меню и помещено в атрибут Menu формы.

В этом случае у меня было главное меню File. Подменю, называемое MenuItem под File, содержало тег Open и было названо menu_File_Open. Работало. Предполагая, что вы

// So you don't have to fully reference the objects.
using System.Windows.Forms;

// More stuff before the real code line, but irrelevant to this discussion.

MenuItem my_menuItem = (MenuItem)Form1.Menu.MenuItems["menu_File_Open"];

// Now you can do what you like with my_menuItem;

Ответ 9

Это может помочь вам:

public Control RecursiveFind(Control ParentCntl, string NameToSearch)
{
    if (ParentCntl.ID == NameToSearch)
        return ParentCntl;

    foreach (Control ChildCntl in ParentCntl.Controls)
    {
        Control ResultCntl = RecursiveFind(ChildCntl , NameToSearch);
        if (ResultCntl != null)
            return ResultCntl;
    }
    return null;
}

Другой подход

myForm.FindControl<Label>("myLabel");

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MyExtensions
{
    public static class Extensions
    {
        public static IEnumerable<T> FindControl<T>(this Control parentControl, String name = "")
        {
            if (parentControl is T)
            {
                if (String.IsNullOrWhiteSpace(name))
                    yield return (T)(object)parentControl;
                else if (parentControl.Name.Equals(name))
                {
                    yield return (T)(object)parentControl;
                    yield break;
                }
            }

            var filteredControlList = from controlList in parentControl.Controls.Cast<Control>()
                                      where controlList is T || controlList.Controls.Count > 0
                                      select controlList;

            foreach (Control childControl in filteredControlList)
            {
                foreach(T foundControl in FindControl<T>(childControl, name))
                {
                    yield return foundControl;
                    if (!String.IsNullOrWhiteSpace(name))
                        yield break;
                }
            }
        }
    }
}

Ответ 10

Используя тот же подход Philip Wallace, мы можем сделать вот так:

    public Control GetControlByName(Control ParentCntl, string NameToSearch)
    {
        if (ParentCntl.Name == NameToSearch)
            return ParentCntl;

        foreach (Control ChildCntl in ParentCntl.Controls)
        {
            Control ResultCntl = GetControlByName(ChildCntl, NameToSearch);
            if (ResultCntl != null)
                return ResultCntl;
        }
        return null;
    }

Пример:

    public void doSomething() 
    {
            TextBox myTextBox = (TextBox) this.GetControlByName(this, "mytextboxname");
            myTextBox.Text = "Hello!";
    }

Я надеюсь, что это поможет!:)

Ответ 11

Посмотрите на коллекцию ToolStrip.Items. Он даже имеет доступный метод поиска.

Ответ 12

Вы можете сделать следующее:

private ToolStripMenuItem getToolStripMenuItemByName(string nameParam)
   {
      foreach (Control ctn in this.Controls)
         {
            if (ctn is ToolStripMenuItem)
               {
                   if (ctn.Name = nameParam)
                      {
                         return ctn;
                      }
                }
         }
         return null;
    }

Ответ 13

Простым решением будет итерация через список Controls в цикле foreach. Что-то вроде этого:

foreach (Control child in Controls)
{
    // Code that executes for each control.
}

Итак, теперь у вас есть итератор, child, который имеет тип Control. Теперь сделайте все, что захотите, лично я нашел это в проекте, который я сделал некоторое время назад, в котором он добавил событие для этого элемента управления, например:

child.MouseDown += new MouseEventHandler(dragDown);

Ответ 14

Один из лучших способов - это одна строка кода:

В этом примере мы ищем все PictureBox по имени в форме

PictureBox[] picSample = 
                    (PictureBox)this.Controls.Find(PIC_SAMPLE_NAME, true);

Наиболее важным является второй параграф find.

если вы уверены, что имя элемента управления существует, вы можете напрямую его использовать:

  PictureBox picSample = 
                        (PictureBox)this.Controls.Find(PIC_SAMPLE_NAME, true)[0];