【发布时间】:2015-01-05 18:47:43
【问题描述】:
我想使用上下文菜单并在局部变量中获取用户的选择。
我尝试使用这样的简单 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 中分配得很好(我可以将其打印到控制台),但之后会重置。
我在this post 中发现,根据 C# 语言规范:
5.3.3.29 匿名函数
对于带有 a 的 lambda 表达式或匿名方法表达式 expr 正文(块或表达式)正文:
外部变量 v 在 body 之前的明确赋值状态与 v 在 expr 之前的状态相同。也就是明确的分配 外部变量的状态是从上下文中继承的 匿名函数。
外层变量v在expr之后的明确赋值状态与v在expr之前的状态相同
好的。现在,我意识到我可以创建一个非匿名函数,但我真的很想使用这种简洁的语法来完成一项像分配一个整数一样微不足道的工作。我想我错过了一些明显的东西?关于 Lambdas?还是关于 ContextMenus?
我尝试了一个属性并更改了 MenueItem,但没有找到 如何从该 lambda 中持久化任何东西..
更新:
现在我已经了解到 menu.Show 不会像 ShowDialog 那样阻塞,我可以简单地将我的代码更改为
mi.Click += (sender, e) => { menuAction( mi) ; };
和
void menuAction(MenuItem choice)
{
//..do my stuff
}
所以我也尝试过的属性更改最终被保留了,但我太早使用了属性,并且对规范的“外部变量”部分过于悲观地阅读了...... p>
【问题讨论】:
-
choice只是赋值,但是用在哪里呢? -
我会在它得到一个值时使用它。我没有包括测试的东西;想象一下
Console.WriteLine("Choice: " + choice); -
你想在这里做什么?您将用户的选择存储在用户选择时将超出范围的本地。这有什么意义?如果您使用 lambda “就地”定义事件处理程序,为什么需要存储任何内容(除非它在当前类中的状态发生变化,在这种情况下您应该使用实例字段,而不是本地字段)?
-
对你有什么好处?但既然你问的是显而易见的:我会根据所做的选择或设置某种模式来调用一些函数。不,实例字段或属性也不起作用,如我的帖子和语言规范中所述。是的,我也可以至少内联这些调用,但这似乎相当笨拙,因为它们需要一些设置..
-
对我有什么影响?对试图帮助的人态度很好。我再给你讲一遍,因为显然它对你来说并不明显。当调用事件处理程序时,您正在分配一个超出范围的本地。
m.Show在用户选择选项之前不会阻止。祝你有美好的一天。
标签: c# menu lambda contextmenu