Reputation: 33
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
Upvotes: 3
Views: 2121
Reputation: 5303
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#
Upvotes: 4
Reputation: 174447
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);
Upvotes: 2