tags:

views:

217

answers:

5

SO this is a dumb question. I have added a bunch of textboxes to an options dialog in an app I've written. They are named textbox1 - textbox12. Is there a way to access the the names programmatically? I'd just like to iterate over them in a for loop. Right now I am accessing each one individually (shudders!). I know this is the wrong way. What is the right way? what is the easy way?

Thanks

+7  A: 
foreach (Control c in this.Controls)
{
    if (c is TextBox)
    {
        // your logic here
    }
}

If they have different functionality, then you might need more checks than just determining that they are the correct type. And of course, this assumes that you have the System.Windows.Forms namespace imported.

John Rudy
+1 You rock. Simpler than I even imagined. WOOT,
Byron Whitlock
Glad to help. I'm sure there's some really cool LINQ-y way to do it, but I'm not a LINQ pro yet. I'd love to see someone else contribute one if that's feasible ...
John Rudy
+2  A: 

You could write a function that does this more generically.

IEnumerable<T> GetChildren<T>(Control owner)
{
    foreach (Control c in owner.Controls)
    {
        if (c is T)
        {
            yield return c as T;
        }
    }
}

Use it this way:

foreach (TextBox tb in GetChildren<TextBox>(optionsControl))
{
    System.Diagnostics.Trace.WriteLine(tb.Name);
}
John Fisher
+5  A: 

The Controls collection allows you to access items by name, so you could do this:

var textboxes = Enumerable.Range(1, 12).Select(i => String.Format("textbox{0}", i)).Select(name => (TextBox)this.Controls[name]);

which will avoid having to enumerate every control in the collection, although is brittle since it depends on the naming convention used.

Alternatively you could just use the OfType query method:

var textboxes = this.Controls.OfType<TextBox>();
Lee
+1 for `var textboxes = this.Controls.OfType<TextBox>();` ... That was exactly what I was talking about looking for myself. :)
John Rudy
Great. +1 for the OfType method
Moshe Levi
Hrm... I think I need to change my code to use OfType!
Sterno
+1  A: 

I had a page that added a variable number of checkboxes to a page via a repeater, and I needed to perform some operations on them. I ended up writing this generic extension method so I could use it for any controls in the future. This would dig down through subcontrols as well, in case your checkbox was inside some other control on the page.

public static List<TChildType> FindChildrenOfType<TChildType>(this Control currentControl)
    where TChildType : Control
{
    var childList = new List<TChildType>();
    foreach (Control childControl in currentControl.Controls)
    {
        if (childControl is TChildType)
        {
            childList.Add((TChildType)childControl);
        }

        childList.AddRange(childControl.FindChildrenOfType<TChildType>());

    }
    return childList;
}

In the page, it got used like this:

var checkedCheckboxes = _myRepeater.FindChildrenOfType<CheckBox>().FindAll(c => c.Checked);
Sterno
Based on some examples above, this would be even better replacing my inner loop with Control.OfType(), but I don't want to change this example until I have a chance to test that.
Sterno
+1  A: 

Personally I prefer to create the controls programatically and then put them in a collection. i.e.

IList<TextBox> textBoxes = new List<TextBox>();

…

    for (int i = 0; i < 12; i += 1)
    {
        TextBox textBox = new TextBox();
        textBox.Position = new Point(FormMargin, FormMargin + (i * (textBox.Height + TextBoxPadding)));
        this.Controls.Add(textBox);
        this.textBoxes.Add(textBox);
    }

You can then just itterate over textBoxes to programatically add them. I find this scales better when you have several different groups of textboxes you need to do this with.

ICR
I knew this is how I needed to do it. This is what I should have done from the start. THANKS!!!!
Byron Whitlock