添加行为以使用代码 C# 进行控制

Adding behaviours to control using code C#

我正在使用 Visual Studio 2017 和 C# 创建 Win Form 应用程序。我正在尝试将鼠标输入行为添加到一组控件中,如下所示;

int i = 0;
foreach(MetroTileItem item in game_tile_panel.Items){

        // THIS MESSAGE BOX DISPLAYS THE CORRECT VALUE
        MessageBox.Show(i.ToString());

        item.MouseEnter += (Object sender, EventArgs e) => {
             // THIS MESSAGE BOX DOES NOT DISPLAY TO CORRECT VALUES
             MessageBox.Show(i.ToString());
        };

        i++;
}

第一个消息框 returns 每个项目的值 i 并正确显示。 MouseEnter 行为内部的第二个消息框不显示 i 的正确值,或者至少不是我期望的值。

当我在运行时执行 MouseEnter 行为时,消息框显示每个项目的值 3。而我希望第一项显示 0,第二项显示 1 等等。

任何人都可以阐明为什么会发生这种情况以及我如何解决它。也许我无法以这种方式添加行为?谢谢

int i = 0;
foreach(MetroTileItem item in game_tile_panel.Items){

    int pickMe = i;    <<<<<<<<<<<<<

    // THIS MESSAGE BOX DISPLAYS THE CORRECT VALUE
    MessageBox.Show(i.ToString());

    item.MouseEnter += (Object sender, EventArgs e) => {
         // THIS MESSAGE BOX DOES NOT DISPLAY TO CORRECT VALUES
         MessageBox.Show(pickMe.ToString());   <<<<<<<<<<<<<<<<
    };

    i++;
}

通过为每次迭代声明一个新变量,可以捕获正确的值。事实上,事件处理程序直到 foreach 完成后的某个时间才被调用,这就是原因。

这是modified closure现象的一个实例:简而言之,您声明为事件处理程序的委托捕获变量 i,而不是i的当前值。这称为闭包。因此,每个事件处理程序在调用它时将值 3 的 i 取消引用,因为这就是你在循环退出时离开 i 的方式。

博客 post 解释了如何使用局部变量来避免这种情况。