Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event-Handler with Delegates

I will create dynamic buttons in C# and I need to add a parameter to the Click-Event-Handler (ID).

But, in this exmaple the output is allways the last parameter "10" for ALL buttons, and not "1-2-3-4-5-....", why?

for(int counter = 1; counter < 10; counter++)
{

    // Add new button

    Button btn = new Button();

    btn.Width = 250;
    btn.Height = 50;

    btn.Click += delegate (object sender1, EventArgs e1)
    { myEventHandler(sender1, e1, counter); };

    Test.Controls.Add(btn);

}


public void myEventHandler(object sender, EventArgs e, int i)
{

    MessageBox.Show("Test: " + i);

}

Thanx for any help!

Florian

like image 305
Florian Avatar asked Jan 18 '26 12:01

Florian


2 Answers

This is because the counter variable is not captured. This means that when the loop finishes the value of counter will be 10, so all delegates will have that value to fix you can use a variable within the loop like this:

for(int counter = 1; counter < 10; counter++)
{

    // Add new button

    Button btn = new Button();

    btn.Width = 250;
    btn.Height = 50;

    int num = counter;
    btn.Click += delegate (object sender1, EventArgs e1)
    { myEventHandler(sender1, e1, num ); };

    Test.Controls.Add(btn);

}


public void myEventHandler(object sender, EventArgs e, int i)
{

    MessageBox.Show("Test: " + i);

}

See this question on stackoverflow for more info Captured variable in a loop in C#

like image 150
Kevin Holditch Avatar answered Jan 21 '26 02:01

Kevin Holditch


That's because the delegate captures the reference of the counter variable and not the value. That means that all ten delegates contain a reference to the very same counter variable. Upon execution of the delegates, this variable naturally has the value 10, because your loop already finished.

Fix it like this:

var tmp = counter;
btn.Click += delegate (object sender1, EventArgs e1)
{ myEventHandler(sender1, e1, tmp); };

Now each delegate will have its own instance.

BTW, you can use the lambda syntax to make this code a little less verbose:

var tmp = counter;
btn.Click += (sender1, e1) => myEventHandler(sender1, e1, tmp);
like image 28
Daniel Hilgarth Avatar answered Jan 21 '26 02:01

Daniel Hilgarth



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!