Jooj
Jooj

Reputation: 707

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"?

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".

How do I do this in Windows Forms at runtime?

Upvotes: 0

Views: 4890

Answers (4)

Bobby
Bobby

Reputation: 11576

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.

Upvotes: 0

Paul Ruane
Paul Ruane

Reputation: 38620

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

Upvotes: 7

SwDevMan81
SwDevMan81

Reputation: 50018

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

Upvotes: 3

Adriaan Stander
Adriaan Stander

Reputation: 166536

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.

Upvotes: 1

Related Questions