ContextMenu和Lambda-这是可能的吗

本文关键字:Lambda- ContextMenu | 更新日期: 2023-09-27 18:29:41

我想使用上下文菜单,并在局部变量中获得用户的选择。

我试着使用这样一个简单的lambda:

void showMenu(Point pos)
{
    ContextMenu m = new ContextMenu();
    int choice = -1;
    var menueChoices = new string[] {"Stretch Mode", "Brightness",  "Saturation", 
                                     "Hues", "Flip Color Stops", "Invert Colors" };
    for (int i = 0; i < menueChoices.Length; i++ )
    {
        MenuItem mi = new MenuItem(menueChoices[i]);
        mi.Index = i;
        mi.Click += (sender, e) =>  { choice = mi.Index; };
        m.MenuItems.Add(i, mi);
    }
    m.Show(flowLayoutPanel1, pos);
    // work with the choice..
}

该选项在lambda中分配得很好(我可以将其打印到控制台),但之后会重置。

我在这篇文章中发现,根据C#语言规范:

5.3.3.29匿名函数

对于具有正文(块或表达式)正文:

  • 外部变量v在body之前的确定赋值状态与v在expr之前的状态相同。即明确分配外部变量的状态是从匿名函数。

  • 外部变量v在expr之后的确定赋值状态与v在expr-之前的状态相同

好的。现在,我意识到我可以创建一个非匿名函数,但我真的很想把这种简洁的语法用于分配一个整数这样琐碎的工作。我想我错过了一些显而易见的东西?关于Lambdas?或者关于ContextMenus??

我尝试了一个属性并更改了MenuItem,但没有找到如何持久化该lambda中的任何东西。。

更新:

现在我已经知道menu.Show不会像ShowDialog那样阻塞,我可以简单地将代码更改为

mi.Click += (sender, e) =>  {  menuAction( mi) ;  };

void menuAction(MenuItem choice)
{
    //..do my stuff
}

因此,我也尝试过的属性更改始终存在,但我过早地使用了属性,并且对规范中的"外部变量"部分的解读有点过于悲观。。

ContextMenu和Lambda-这是可能的吗

您似乎认为在ContextMenu上调用Show将被阻止,直到菜单关闭。

事实上,情况并非如此,showMenu方法将在显示菜单后、用户选择项目之前立即退出,此时您的choice本地将是空白的。

您必须使用实例或以其他方式引用的变量将所选内容存储在.中

通常,您会在包含showMenu的类上定义一个字段,并在lambda中引用该字段。

但是,只有当用户在ContextMenu上调用Show之后选择了一个而非项目时,才会填充该字段。