General recursive method for iterate all controls and their related controls in a windows form

StackOverflow https://stackoverflow.com/questions/14483948

Pregunta

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?

¿Fue útil?

Solución

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.

Otros consejos

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top