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
上调用Show
将被阻止,直到菜单关闭。
事实上,情况并非如此,showMenu
方法将在显示菜单后、用户选择项目之前立即退出,此时您的choice
本地将是空白的。
您必须使用实例或以其他方式引用的变量将所选内容存储在.中
通常,您会在包含showMenu
的类上定义一个字段,并在lambda中引用该字段。
但是,只有当用户在ContextMenu
上调用Show
之后选择了一个而非项目时,才会填充该字段。