Question

Is there any general recursive method that can iterate all controls(include toolstrip and its items, bindingnavigator and its items,...) in a windows form? (some of them are not inherited from Control class) or at least iterate toolstrip and its items, bindingnavigator and its items?

Was it helpful?

Solution

You're going to run into a snag here because ToolStrip uses Items instead of Controls, and ToolStripItem does not inherit from Control. Both ToolStripItem and Control inherit from Component, so at best you can get an IEnumerable<Component>.

You could accomplish this with the following extension method:

public static class ComponentExtensions
{
    public static IEnumerable<Component> GetAllComponents(this Component component)
    {
        IEnumerable<Component> components;
        if (component is ToolStrip) components = ((ToolStrip)component).Items.Cast<Component>();
        else if (component is Control) components = ((Control)component).Controls.Cast<Component>();
        else components = Enumerable.Empty<Component>();    //  figure out what you want to do here
        return components.Concat(components.SelectMany(x => x.GetAllComponents()));
    }
}

On a Windows Form you could process all of these components in a foreach loop:

foreach (Component component in this.GetAllComponents())
{
    //    Do something with component...
}

Unfortunately, you'll do a lot of manual type checking and casting.

OTHER TIPS

This is what I usually do in this case:

First of all define a delegate that accept a Control as parameter:

public delegate void DoSomethingWithControl(Control c);

Then implement a method that takes this delegate as the first parameter, and the control upon which to recursively execute it as the second. This methods first executes the delegate, then loops on the Controls collection of the control to recursively call itself. This works since Controls is defined in Control and returns an empty collection for simple controls like:

public void RecursivelyDoOnControls(DoSomethingWithControl aDel, Control aCtrl)
{
    aDel(aCtrl);
    foreach (Control c in aCtrl.Controls)
    {
        RecursivelyDoOnControls(aDel, c);
    }
}

Now you can put the code you want to execute for each control in a method and call it on the Form through the delegate:

private void DoStg(Control c)
{
    // whatever you want
}

RecursivelyDoOnControls(new DoSomethingWithControl(DoStg), yourForm);

EDIT:

Since you are dealing with ToolStripItems, too, you could define the delegate to deal with generic objects, and then write different overloads of the recursive method. I.e. something like this:

public delegate void DoSomethingWithObject(Object o);

public void RecursivelyDo(DoSomethingWithObject aDel, Control aCtrl)
{
    aDel(aCtrl);
    foreach (Control c in aCtrl.Controls)
    {
        RecursivelyDoOnControls(aDel, c);
    }
}

public void RecursivelyDo(DoSomethingWithObject aDel, ToolStrip anItem)
{
    aDel(anItem);
    foreach (ToolstripItem c in anItem.Items)
    {
        RecursivelyDo(aDel, c);
    }
}

public void RecursivelyDo(DoSomethingWithObject aDel, ToolStripDropDownButton anItem)
{
    aDel(anItem);
    foreach (ToolStripItem c in anItem.DropDownItems)
    {
        RecursivelyDo(aDel, c);
    }
}

//and so on
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top