tags:

views:

112

answers:

4

i have a win form named A , A contains lots of different controls ,first contains a main groubbox and this groupbox countains lots of table and others group boxes. i want to find a control which has tab index 9(example) in form A but i dont know which groubox contains this control. how i found this control.

regards Shailesh

+1  A: 

Recursively search through your form's Controls collection.

    void FindAndSayHi( Control control )
    {
        foreach ( Control c in control.Controls )
        {
            Find( c.Controls );
            if ( c.TabIndex == 9 )
            {
                MessageBox.Show( "Hi" );
            }
        }
    }
Ed Swangren
A: 
void iterateControls(Control ctrl)
{
    foreach(Control c in ctrl.Controls)
    {
        iterateControls(c);
    }
}
thelost
+2  A: 

You can make a method like this:

public static Control GetControl(Control.ControlCollection controlCollection, Predicate<Control> match)
{
    foreach (Control control in controlCollection)
    {
        if (match(control))
        {
            return control;
        }

        if (control.Controls.Count > 0)
        {
            Control result = GetControl(control.Controls, match);
            if (result != null)
            {
                return result;
            }
        }
    }

    return null;
}

...that is used like this:

Control control = GetControl(this.Controls, ctl => ctl.TabIndex == 9);

Note however that TabIndex is a tricky case, since it starts at 0 within each container, so there may be several controls in the same form having the same TabIndex value.

Either way, the method above can be used for checking pretty much any property of the controls:

Control control = GetControl(this.Controls, ctl => ctl.Text == "Some text");
Fredrik Mörk
+5  A: 

With recursion...

public static IEnumerable<T> Descendants<T>( this Control control ) where T : class
{

    foreach ( Control child in control.Controls ) {

        T childOfT = child as T;
        if ( childOfT != null ) {
            yield return (T)childOfT;
        }

        if ( child.HasChildren ) {
            foreach ( T descendant in Descendants<T>( child ) ) {
                yield return descendant;
            }
        }

    }

}

You can use the above function like:

var checkBox = (from c in myForm.Descendants<CheckBox>()
                where c.TabIndex == 9
                select c).FirstOrDefault();

That will get the first CheckBox anywhere within the form that has a TabIndex of 9. You can obviously use whatever criteria you want.

EDIT
If you aren't a fan of LINQ query syntax, the above could be re-written as:

var checkBox = myForm.Descendants<CheckBox>()
                     .FirstOrDefault(x=>x.TabIndex==9);
Josh Einstein
Wow, that is an extreme, overly complicated way to find a control with a tab index of 9. Kudos for effort though.
Ed Swangren
Your method only finds a control with a tab index of 9. Mine is an extension method that effectively enables LINQ to WinForms. It's the same approach used by LINQ to XML. And it's hardly complicated, it's simple recursion like many of the other answers. The only difference being I'm filtering on type which makes the predicate easier to write.
Josh Einstein
Ok, I can add an int parameter and now it does that. Seriously though, you will never need any of that, you just need to find a control with a tab index equal to n, and people have to stare at that for at least a few seconds to even figure out what it does. Also, I would prefer to write Find( this, 9 ) instead of a query, but I didn't mean to be rude, this is a place for having some fun with code after all.
Ed Swangren
+1 for checking on the type and the yield return will also ensure that no more controls that need to be evaluated will be evaluated. Could also easily be applied to many other conditions without modifying the extension method and could check on properties specific to the type (like `IsChecked`) as well!@Ed Swangren what if you don't want to check on TabIndex anymore? A query (or predicate) is not a bad idea.
Cornelius
I guess you're not used to LINQ. I've shown a general method of finding one or more controls "n" levels deep that meet a given criteria. It's quite powerful (even for a 7 line function) and yes, I used it quite a bit when I used to write WinForms apps and I have a similar method for WPF now.
Josh Einstein
@Ed: the elegance of this solution appears when, in a near future, the need to find a control that has no child controls appears. You can reuse the code, just call it with a different comparison, instead of extending the code base with a new, nearly identical method for that new case.
Fredrik Mörk
Yeesh, mine was just a quick and dirty example. Honestly, if I saw that in production code and it was only ever used to find a tab index I would cringe a bit, but whatever, I never said it was wrong in any way, just overly engineered.
Ed Swangren