有没有办法显示“阻塞” WinForms 上下文菜单?
有没有办法显示 ContextMenu 并阻止进一步执行,直到选择一个项目?特别是,我希望获得与 ShowDialog()
类似的行为,但适用于 ContextMenu
。
直接的方法不起作用:
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("1", (s,e) => {value = 1;});
cm.Show(control, location);
因为 Click
回调不是直接从 Show()
调用的,而是在稍后消息循环处理点击事件时调用。
如果您运气不好,menu
会在处理事件之前被垃圾回收,在这种情况下,事件会默默地丢失。 (这意味着您不能以这种方式真正使用 ContextMenu 的局部变量。)
这似乎可行,但感觉“不干净”:
using (ContextMenu cm = new ContextMenu()) {
cm.MenuItems.Add("1", (s,e) => {value = 1;});
cm.Show(control, location);
Application.DoEvents();
}
有更好的方法吗?
Is there a way to show a ContextMenu
and block further execution until an item has been selected? In particular, I want to get behavior similar to ShowDialog()
but for a ContextMenu
.
The straight forward approach doesn't work:
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("1", (s,e) => {value = 1;});
cm.Show(control, location);
since the Click
callback isn't called directly from Show()
but instead at some later point when the message loop processes the click event.
If you are unlucky, menu
is garbage collected before the event is processed and in that case the event is just silently lost. (Meaning you can't really use local variables for ContextMenu
s in this way.)
This seems to work, but feels "unclean":
using (ContextMenu cm = new ContextMenu()) {
cm.MenuItems.Add("1", (s,e) => {value = 1;});
cm.Show(control, location);
Application.DoEvents();
}
Is there a better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
抱歉第一个答案。这是我尝试过的。我制作了另一个表单,在其中放置了上下文菜单和计时器。Form2 从 Form1 显示为模态,然后计时器在 Form2 上显示上下文菜单。
请注意,Form 2 设置了一些属性:在任务栏中不可见、没有边框以及大小应与上下文菜单的大小相同。
希望这有帮助。
Sorry for the first answer. Here is what I've tried. I made another Form where I put the context menu and a timer.Form2 is displayed as modal from Form1 then the timer shows the context menu on Form2.
Note that Form 2 has some properties set : to not be visible in task bar, not have boarders and the size should be equal with the size of the context menu.
Hope this helps.
您可以轻松地阻止 ContextMenu 在显示时进行垃圾回收。
问题是您使用 lambda 作为菜单项的事件处理程序。这是一个
匿名方法,因此本身不会附加到任何对象实例,这会导致 ContextMenu 被引用并保持活动状态。向封闭对象添加一个方法,然后创建一个标准的 EventHandler。这样,封闭实例的存在将使 ContextMenu 保持活动状态。不像 C# 1.0 那样简洁,但它可以解决问题。
You can easily prevent the garbage collection of the ContextMenu whilst it is still being shown.
The problem is that you are using a lambda as the event handler for the menu item. This is an
anonymous method and so not itself attached to any object instance that would cause the ContextMenu to be referenced and so kept alive. Add a method to the enclosing object and then create a standard EventHandler. That way the existence of the enclosing instance will keep the ContextMenu alive. Not as concise and very C# 1.0 but it will solve the problem.
只需等待菜单不可见即可。
Just wait for the menu to not be visiable.