tags:

views:

251

answers:

4

Is there a simple way to get all controls that contains the property ".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".

Does somebody know how to do this in winforms at runtime?

Best regards.

A: 

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.

astander
A: 

Recursion might be a solution, having a function which takes a control and returns all of it's children (which calls itself on all children). That way you'd get a flat array of controls.

Bobby
+7  A: 

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.

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.

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. Obviously one approach would be to exclude those controls that have an empty string for the Text property.

One can also do something similar for the menu (note that you will need to modify this somewhat if you are using the 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);
    }
}
Paul Ruane
@Paul Ruane: you code also doesn't list menuitems.:(
Jooj
I think one would have to handle menus explicitly as they do not derive from Control and there is no 'Components' collection we could iterate that contains all of the Form's components. The premise is the same as above, but instead of Control one would iterate Menu items instead. I'll update the answer to illustrate.
Paul Ruane
your code look great, but this.Menu is always null. I'm using a toolstipcontainer...
Jooj
You should be able to apply the principles to that too — you could add a line in the loop that checks whether the control is a ToolStripContainer and then looks at the ToolStripMenuItems recursively.
Paul Ruane
@Paul Except there does not seem to be any container object in a ToolStripItem.
Loren Pechtel
+2  A: 

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);
        }
     }
  }
SwDevMan81
It is impossible for a Control to not have a Text property as it is a member of the Control class, so the condition of the if statement is actually an elaborate true.
Paul Ruane
@SwDevMan81: this is similar to my method. But it doesn't find menuitem texts.
Jooj