简体   繁体   English

如何使用C#在运行时从表单获取所有控件?

[英]How to get all controls from a form at runtime in C#?

Is there a simple way to get all controls that contains the property ".Text" ? 是否有一种简单的方法来获取包含属性".Text"所有控件?

I'm able to get all "top level" controls, but my code doesn't find sub controls like menu items on all levels, etc. I also tried "ctrl.HasChildren" . 我可以获取所有"top level"控件,但是我的代码找不到所有级别的menu items等子控件。我也尝试了"ctrl.HasChildren"

How do I do this in Windows Forms at runtime? 在运行时如何在Windows窗体中执行此操作?

Every control that derives from Control has a Text property, which is every control — however for some controls this property does not have a meaning. 从Control派生的每个控件都具有Text属性,即每个控件-但是,对于某些控件,此属性没有意义。

To build the complete list of controls you need to iterate the Form's Controls collection and then, for each control within it, recursively iterate that control's Controls collection. 若要构建控件的完整列表,您需要迭代Form的Controls集合,然后对其中的每个控件递归地迭代该控件的Controls集合。

IList<Control> controlsOnForm = new List<Control>();
BuildControlsList(this.Controls, controlsOnForm);

private static void BuildControlsList(ControlCollection controls, IList<Control> listToPopulate)
{
    foreach (Control childControl in controls)
    {
        listToPopulate.Add(childControl);
        BuildControlsList(childControl.Controls, listToPopulate);
    }
}

I'm not actually sure how you are going to differentiate between controls that have a useful Text property and those for which it is not used. 我实际上不确定如何区分具有有用的Text属性的控件和未使用它的控件。 Obviously one approach would be to exclude those controls that have an empty string for the Text property. 显然,一种方法是排除那些Text属性为空字符串的控件。

One can also do something similar for the menu (note that you will need to modify this somewhat if you are using the MainMenuStrip): 也可以对菜单执行类似的操作(请注意,如果使用MainMenuStrip,则需要对此进行一些修改):

IList<Menu> menusOnForm = new List<Menu>();
if (this.Menu != null)
{
    menusOnForm.Add(this.Menu);
    BuildMenuList(this.Menu.MenuItems, menusOnForm);
}

private static void BuildMenusList(MenuItemCollection menuItems, IList<Menu> listToPopulate)
{
    foreach (Menu menuItem in menuItems)
    {
        listToPopulate.Add(menuItem);
        BuildMenusList(menuItem.MenuItems, listToPopulate);
    }
}

You could loop through each control and use reflection to find the property Name Text 您可以遍历每个控件并使用反射来查找属性名称文本

     foreach (Control contrl in this.Controls)
     {
        if (contrl.GetType().GetProperty("Text") != null)
        {
           // contrl has Text Property
        }
     }

Adding in the search for all controls 在搜索中添加所有控件

  List<Control> text_controls = new List<Control>();
  FindAllControls(this.Controls, text_controls);

  private void FindAllControls(Control.ControlCollection controls, List<Control> ctrlsWithTextProperty)
  {
     foreach(Control ctrl in controls)
     {
        if(ctrl.GetType().GetProperty("Text") != null)
        {
           ctrlsWithTextProperty.Add(ctrl);
        }
        if (ctrl.Controls != null)
        {
           FindAllControls(ctrl.Controls, ctrlsWithTextProperty);
        }
     }
  }

You should be able to check 您应该可以检查

if(control.Controls.Count > 0)

With this you can then recursively call your method to loop down the control tree. 这样,您就可以递归地调用您的方法来遍历控制树。

Recursion might be a solution, having a function which takes a control and returns all of its children (which calls itself on all children). 递归可能是一种解决方案,它具有一个接受控制并返回其所有子代的函数(在所有子代上调用自身)。

That way you'd get a flat array of controls. 这样,您将获得一系列平面控件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM