How to iterate over windows forms controls

Viewed 798

I have 5 textboxes with 5 labels,named like this:

  • text1, text2, text3, etc.
  • label1, label2, label3, etc.

What I want to do is to target each of them and apply the same code, without having to write something individually. I was thinking about a loop like this:

for (int i = 1; i <= 5; i++)
{
    try
    {
        tcpCLient.ConnectAsync(text(i).Text, 80);
        label(i).Text = "Online";
    }
    catch (Exception)
    {
        label(i).Text = "Offline";
    }
}

The problem is that Visual Studio won't let me compile as "The name 'text' does not exist in the current context".

Is this the wrong approach? How would you do this?

Thank you very much!

4 Answers

Well, the code label(i).Text is not well-formed. That seems like you are trying to call a function label with parameter i and access the member Text of such result.

You could do something like this

Label[] labels = { label1, label2, label3, label4, label5 };
TextBox[] textBoxes = { text1, text2, text3, text4, text5 };

for (int i = 0; i < 5; i++)
{
    try
    {
        tcpCLient.ConnectAsync(textBoxes[i].Text, 80);
        labels[i].Text = "Online";
    }
    catch (Exception)
    {
        labels[i].Text = "Offline";
    }
}

"The name 'text' does not exist in the current context".

text[i].Text you can only do this if text type implements IEnumerable

You can do this to enumerate over your controls

var labels = new List<Label> { label1, label2, label3};
var textBoxs = new List<TextBox> { text1, text2, text3};


for (int i = 1; i <= 5; i++)
{
    try
    {
        tcpCLient.ConnectAsync(textBoxs[i].Text, 80);
        labels[i].Text = "Online";
    }
    catch (Exception)
    {
        labels[i].Text = "Offline";
    }
}

You can iterate a Form's Controls through its ControlCollection.

See Form.ControlCollection.

But mind that this includes all controls. If you want to pick specific ones, you'd have to filter by type and/or name.

That out of the way, I'd strongly advise to go a different route, though. I'd make a UserControl and make use of the MVC pattern in conjunction with Binding.

Also mind, that your code won't work as expected, since it seems to try to connect the same instance of TcpClient to 4 different Endpoints.

In windows forms you can iterate over the Forms.Controls to get all the labels and textboxes in a more automated way.

Example:

List<TextBox> textBoxes = Controls.OfType<TextBox>()
    .Where(txt => txt.Name.StartsWith("text"))
    .ToList();

List<Label> labels = Controls.OfType<Label>()
    .Where(lbl => lbl.Name.StartsWith("label"))
    .ToList();

for (int i = 0; i < textBoxes.Count; i++)
{
    try
    {
        tcpCLient.ConnectAsync(text(i).Text, 80);
        labels[i].Text = "Online";
    }
    catch (Exception)
    {
        textBoxes[i].Text = "Offline";
    }
}

Note: This way you can only get the immediate children of the Form. If the textboxes and labels are children of a different parent control (e.g. Panel), you will need to iterate over the Controls property of that parent control. To iterate over all the control of a Form see: Loop through all controls on a form,even those in groupboxes

Related