简体   繁体   中英

How to create an event handler for multiple buttons using a for loop?

I want to set 50 button's click event to - private void buttonOnOff(object sender, EventArgs e).

It works when I write my code like this:

    public Form1()
    {
        InitializeComponent();

        button1.Click += button_Click;
        button2.Click += button_Click;
        button3.Click += button_Click;
       .......
    }

But is it possible do do this using a for loop. When I try I get the following error: Object reference not set to an instance of an object.

The error is on this line of code: Controls[buttonName].Click += buttonOnOff;

Here is the code I'm currently using:

    public Form1()
    {
        InitializeComponent();

        string buttonName;

        for (int i = 1; i < 51; i++)    // Does a check for each button.
        {
            buttonName = "button" + i;
            Controls[buttonName].Click += buttonOnOff;
        }
    }

You can iterate over the forms controls (and even specifically buttons using Linq) - something like this:

foreach (Button b in this.Controls.OfType<Button>())
{
    // here, you could check the name, if necessary
    // and add your handler
    b.Click += buttonOnOff;
}

Elevating some good comments to add to the answer:

As @mars-red and @donboitnott point out, don't allow this code to execute more than once. In your current example, you are doing it in the Form's constructor, so that is good.

Also, @mars-red mentions the Tag property of your buttons. If you had other buttons on your form and didn't want to try to figure out which buttons, you could add a specific value to the Tag of each and just check that - so, something like this:

foreach (Button b in this.Controls.OfType<Button>())
{
    if (b.Tag.ToString() == "SomeIndicator")
    {
        b.Click += buttonOnOff;
    }
}

And, of course, you could also just look for a particular pattern in the names of the buttons.

Your "object reference" issue doesn't make sense if you are using this code. The iterator is giving you specific instances of buttons, so "b" should always be a button in the loop.

Final Update:

The main issue was that the Form wasn't the "container" of the button controls (they were in a panel). So, instead of using the Form's controls, the user should have been using the Panel's controls (something like this):

SomePanel.Controls[buttonName].Click += buttonOnOff;

At first declare a control array variable and add your buttons to it.

Control[] B_list = new Control[] { Button1, Button2, Button3, ...... }

Then in the for loop, use these serially like

Button btn;
for(int index = 0; index < 50; index++)
{
   btn = (Button)B_list[index];
   btn.Click += new EventHandler(buttonOnOff);
}

OK, undeleting this in request of @Servy:

In the loop you are getting the button controls by name from the controls list. Your exception "Object reference not set to an instance of an object" simply means that there is no object with this name in the list.

So either there is a button missing or named else in your 1-50 set.

If you are using @snow_FFFFFF's solution and the error persists that is really strange.

Nevertheless, as I already suggested: debug the loop! Check on which button name/instance it crashes, check the contents of Controls (you have to go a bit down the private members) etc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM