在 C# 中按名称获取 Windows 窗体控件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1536739/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 18:32:36  来源:igfitidea点击:

Get a Windows Forms control by name in C#

c#winformsstringcontrolsaccessibility

提问by

I have a ToolStripMenuItemcalled myMenu. How can I access this like so:

我有一个ToolStripMenuItemmyMenu. 我怎样才能像这样访问它:

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

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

This is because I am dynamically generating ToolStripMenuItems from an XML file and need to reference MenuItems by their dynamically generated names.

这是因为我从 XML 文件动态生成 ToolStripMenuItems,并且需要通过它们动态生成的名称来引用 MenuItems。

采纳答案by Adriaan Stander

Use the Control.ControlCollection.Findmethod.

使用Control.ControlCollection.Find方法。

Try this:

尝试这个:

this.Controls.Find()

回答by anonymous coward

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

    return null;
}

Disregard this, I reinvent wheels.

忽略这一点,我重新发明轮子。

回答by Julien Lebosquain

Since you're generating them dynamically, keep a map between a string and the menu item, that will allow fast retrieval.

由于您是动态生成它们,因此在字符串和菜单项之间保留一个映射,这将允许快速检索。

// 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>"];

回答by Neil

Have a look at the ToolStrip.Items collection. It even has a find method available.

查看 ToolStrip.Items 集合。它甚至有一个可用的查找方法。

回答by Koekiebox

You can do the following:

您可以执行以下操作:

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

回答by vaNIts

string name = "the_name_you_know";

Control ctn = this.Controls[name];

ctn.Text = "Example...";

回答by Philip Wallace

this.Controls["name"];

This is the actual code that is ran:

这是运行的实际代码:

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;
    }
}

vs:

对比:

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;
}

回答by o3o

this.Controls.Find(name, searchAllChildren)doesn't find ToolStripItem because ToolStripItemis not a Control

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)); 
        }
     }
  }

回答by dmihailescu

Assuming you have the menuStripobject and the menu is only one level deep, use:

假设您有menuStrip对象并且菜单只有一层深,请使用:

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

For deeper menu levels add more SelectMany operators in the statement.

对于更深的菜单级别,在语句中添加更多 SelectMany 运算符。

if you want to search all menu items in the strip then use

如果要搜索条中的所有菜单项,请使用

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

However, make sure each menu has a different name to avoid exception thrown by key duplicates.

但是,请确保每个菜单都有不同的名称,以避免键重复引发异常。

To avoid exceptions you could use FirstOrDefaultinstead of SingleOrDefault/ Single, or just return a sequence if you might have Nameduplicates.

为避免异常,您可以使用/FirstOrDefault代替,或者如果您可能有重复,则只返回一个序列。SingleOrDefaultSingleName

回答by shooky56

Assuming you have Windows.Form Form1as the parent form which owns the menu you've created. One of the form's attributes is named .Menu. If the menu was created programmatically, it should be the same, and it would be recognized as a menu and placed in the Menu attribute of the Form.

假设您Windows.Form Form1拥有拥有您创建的菜单的父表单。表单的属性之一名为.Menu。如果菜单是以编程方式创建的,它应该是相同的,它会被识别为一个菜单并放置在 Form 的 Menu 属性中。

In this case, I had a main menu called File. A sub menu, called a MenuItemunder Filecontained the tag Openand was named menu_File_Open. The following worked. Assuming you

在这种情况下,我有一个名为 的主菜单File。一个名为MenuItemunder 的子菜单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;