通过在C#中的名称获取Windows窗体控件

我有一个名为“myMenu”的ToolStripMenuItem。 我怎样才能访问这样的:

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

这是因为我从XML文件dynamic生成ToolStripMenuItems,并需要通过dynamic生成的名称来引用菜单项。

使用Control.ControlCollection.Find方法。

尝试这个:

 this.Controls.Find() 
 string name = "the_name_you_know"; Control ctn = this.Controls[name]; ctn.Text = "Example..."; 
 Control GetControlByName(string Name) { foreach(Control c in this.Controls) if(c.Name == Name) return c; return null; } 

无视这个,我重塑了车轮。

假设你有menuStrip对象并且菜单只有一个深度,使用:

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

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

如果你想search条中的所有菜单项然后使用

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

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

为了避免exception,你可以使用FirstOrDefault而不是SingleOrDefault / Single ,或者如果你可能有Name重复,就返回一个序列。

this.Controls.Find(name,searchAllChildren)找不到ToolStripItem,因为ToolStripItem不是一个Control

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

由于您是dynamic生成它们,请在string和菜单项之间保留一个映射,以便快速检索。

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

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

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

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

这可以帮助你:

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

使用菲利普·华莱士的相同方法,我们可以这样做:

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

我希望它有帮助! 🙂

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

您可以执行以下操作:

私人ToolStripMenuItem getToolStripMenuItemByName(string名称参数)
    {
       foreach(控制在这个控制ctn)
          {
            如果(ctn是ToolStripMenuItem)
                {
                   如果(ctn.Name = nameParam)
                       {
                         返回ctn;
                       }
                 }
          }
         返回null;
     }

一个简单的解决scheme是遍历foreach循环中的Controls列表。 像这样的东西:

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

所以现在你有你的迭代器, child ,这是types的Control 。 现在做你将要做的事,个人我在一个我刚才做的项目中发现了这个项目,在这个项目中添加了一个这个控件的事件,就像这样:

 child.MouseDown += new MouseEventHandler(dragDown);