Search code examples
c#.netcontrolsevent-handlingcontrol-array

How can I get the array index of a given object in C# with control arrays?


I am dynamically adding a bunch of controls to a form. Each control calls the same method, and in that method I need to know the array index of the the control that performed the action.

CheckBox[] myCB = new CheckBox[100];
int i;
for (i = 0; i < 100; i++)
{
    myCB[i] = new CheckBox();
    myCB[i].Text = "Clicky!";
    myCB[i].Click += new System.EventHandler(dynamicbutton_Click);
    tableLayoutPanel1.Controls.Add(myCB[i]);
}

private void dynamicbutton_Click(Object sender, System.EventArgs e)
{
    label1.Text = sender.???array index property???.ToString();
}

So if I click myCB[42] label1 will read "42" Of course, if there is an easier way to handle dynamic controls I'd appreciate pointers.


Solution

  • One obvious solution would be to set the tag:

    CheckBox[] myCB = new CheckBox[100];
    for (int i = 0; i < myCB.Length; i++)
    {
        myCB[i] = new CheckBox();
        myCB[i].Text = "Clicky!";
        myCB[i].Click += new System.EventHandler(dynamicbutton_Click);
        myCB[i].Tag = i;
        tableLayoutPanel1.Controls.Add(myCB[i]);
    }
    

    Then:

    private void dynamicbutton_Click(Object sender, System.EventArgs e)
    {
        Control control = (Control) sender;
        label1.Text = sender.Tag.ToString();
    }
    

    Another alternative is to capture the information in the event handler, most simply using a lambda expression or anonymous method:

    CheckBox[] myCB = new CheckBox[100];
    for (int i = 0; i < myCB.Length; i++)
    {
        int index = i; // This is very important, as otherwise i will
                      // be captured for all of them
        myCB[i] = new CheckBox();
        myCB[i].Text = "Clicky!";
        myCB[i].Click += (s, e) => label1.Text = index.ToString();
        tableLayoutPanel1.Controls.Add(myCB[i]);
    }
    

    or for more complicated behaviour:

    CheckBox[] myCB = new CheckBox[100];
    for (int i = 0; i < myCB.Length; i++)
    {
        int index= i; // This is very important, as otherwise i will
                      // be captured for all of them
        myCB[i] = new CheckBox();
        myCB[i].Text = "Clicky!";
        myCB[i].Click += (s, e) => DoSomethingComplicated(index, s, e);
        tableLayoutPanel1.Controls.Add(myCB[i]);
    }
    

    (where you declare DoSomethingComplicated appropriately).