我试图将EventHandler挂钩到动态创建的对象上。在此示例中,我使用简单的窗口.Net TabControl来包含动态对象。为简单起见,我使用Button及其Click事件。 重点是每个TabPage上的按钮点击应产生不同的输出。
public partial class Form1 : Form
{
int letter = 65;
private void simpleButton1_Click(object sender, EventArgs e)
{
TabPage newPage = new TabPage();
tabControl1.TabPages.Add(newPage);
Button btn = new Button();
newPage.Controls.Add(btn);
btn.Click += (object s, EventArgs ee) =>
{
// Button on FirstPage should produce "Test A"
// Button on SecondPage should produce "Test B"
Debug.WriteLine("Test " + (char)letter);
};
letter++;
}
}
但是,无论我在任何页面上点击哪个按钮都会产生最后一页的输出(即4个TabPages,所有按钮点击生成"测试D")。感觉就好像引用指针 Button btn 指向每个页面上的所有按钮实例。
我的假设:
Button btn = new Button();
每次执行此行时,指针btn是否指向Button的新实例?在那个意义上:
btn.Click += (object s, EventArgs ee) =>
btn.Click应该是新创建的Button实例的EventHandler,对吧?似乎指针btn仍然引用了Button的所有实例。
请在这件事上赐教。提前谢谢。
答案 0 :(得分:1)
lambda表达式捕获对类中定义的letter
字段的引用,因此该方法将始终使用存储在其中的最新值。
要在创建按钮时捕获letter
的值,首先要创建一个局部变量来复制int
值,然后捕获lambda表达式中的局部变量。
// Create a copy of the value
var character = (char)letter;
// Now the lambda will capture the local variable
btn.Click += (object s, EventArgs ee) =>
{
Debug.WriteLine("Test " + character);
};
这对for loops
的工作方式相同。
请参阅:
答案 1 :(得分:0)
变量只能包含一个值。
您有 N 个不同的按钮和 N 不同的事件处理程序。
但是,您只有一个letter
字段,因此它们都做同样的事情。
相反,您可以在函数内部创建局部变量;然后,每个按钮将通过closures使用自己的变量。