我将在C#中创建动态按钮,我需要在Click-Event-Handler(ID)中添加一个参数。
但是,在这个例子中,输出总是最后一个参数“10”对于所有按钮,而不是“1-2-3-4-5 -....”,为什么?
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任何帮助!
弗洛里安
答案 0 :(得分:3)
这是因为未捕获计数器变量。这意味着当循环结束时,counter的值将为10,因此所有代理都将具有该值来修复您可以在循环中使用变量,如下所示:
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);
}
有关详情,请参阅stackoverflow上的此问题Captured variable in a loop in C#
答案 1 :(得分:2)
这是因为委托捕获了counter
变量的引用而不是值。这意味着所有十个代表都包含对同一counter
变量的引用。在执行委托时,此变量自然具有值10,因为您的循环已经完成。
修复如下:
var tmp = counter;
btn.Click += delegate (object sender1, EventArgs e1)
{ myEventHandler(sender1, e1, tmp); };
现在每个代表都有自己的实例。
顺便说一句,您可以使用lambda语法使这段代码更简洁:
var tmp = counter;
btn.Click += (sender1, e1) => myEventHandler(sender1, e1, tmp);