将变量传递给Click事件

时间:2014-01-10 03:22:36

标签: c# button parameters click

我有以下代码用于创建动态按钮但消息框总是显示8.当我点击button[0][4]时,如何在示例4中显示它?我已经尝试过labda和delegate但是两个都返回8(text[i].Count)。变量i也发生了同样的事情。 它必须是非常简单的东西,但我无法找到它: - (。

private void Form1_Load(object sender, EventArgs e)
{
    for(int i = 0; i < text.Count; i++) // text.Count is 3
    {
        for(int a = 0; a < text[i].Count; a++) // text[i].Count is 8
        {
            button[i][a].Location = new Point(230, 30 +22 *a);
            button[i][a].Text = "Done" + i + " " + a;
            button[i][a].Click += delegate { click(a); };
...

private void click(int a)
{
    MessageBox.Show("" +a);
}

2 个答案:

答案 0 :(得分:4)

你正在关闭闭包内的循环变量 当事件触发时,该变量始终等于最后一项。

相反,你需要在循环中声明单独的变量,因此每个lambda都将捕获它自己永远不会改变的变量。

答案 1 :(得分:2)

由于SLaks还没有给出一个例子......我会的。以下是您的问题的小型重新创建:

internal class Test
{
    public EventHandler Click;
}

..然后主要方法:

var list = new List<Test>();

for (int i = 0; i < 6; i++)
{
    Test t = new Test();
    t.Click += delegate
    {
        click(a);
    };

    list.Add(t);
}

foreach (var t in list)
{
    t.Click(null, null); // 6, 6, 6, 6, 6
}

您需要在循环内创建一个局部变量,因此每个闭包都有自己的副本:

var list = new List<Test>();

for (int i = 0; i < 6; i++)
{
    int a = i; /* <--------------- THIS LINE HERE ------------------ */
    Test t = new Test();
    t.Click += delegate
    {
        click(a); // use the new variable here
    };

    list.Add(t);
}

foreach (var t in list)
{
    t.Click(null, null); // 0, 1, 2, 3, 4, 5
}

产生正确的输出。