代表的事件处理程序

时间:2012-11-23 08:42:48

标签: c# event-handling

我将在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任何帮助!

弗洛里安

2 个答案:

答案 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);