【发布时间】:2026-02-02 19:55:02
【问题描述】:
我喜欢以编程方式创建我的上下文菜单。我通常不会在 contextmenustrip 打开之前将项目添加到它,因为显示的项目取决于设计的其他可变方面。
我发现 contextmenustrips 似乎需要两次右键才能显示。我尝试在不同的事件(打开、打开等)中添加菜单项,并手动将 contextmenustrip 的可见性设置为 true 无济于事。
我终其一生都无法弄清楚为什么需要单击两次右键。如果您创建一个空白的 winforms 项目,然后用它替换所有代码,它将证明问题。
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim currContextMenuStrip As New ContextMenuStrip
Me.ContextMenuStrip = currContextMenuStrip
AddHandler currContextMenuStrip.Opening, AddressOf ContextMenuStrip1_Opening
End Sub
Private Sub ContextMenuStrip1_Opening(sender As Object, e As CancelEventArgs)
Dim currContextMenuStrip As ContextMenuStrip = sender
Dim menuTxt As String = "&Find"
'only add the menu if it doesn't already exist
If (From f In currContextMenuStrip.Items Where f.text = menuTxt).Count = 0 Then
Dim newMenuItem As New ToolStripMenuItem
newMenuItem.Text = menuTxt
currContextMenuStrip.Items.Add(newMenuItem)
End If
End Sub
End Class
编辑:刚刚发现它似乎与第一次右键单击时 contextmenustrip 没有任何项目的事实有关。如果我添加一个虚拟项目,然后在添加其他项目后将其隐藏,它在第一次右键单击时起作用。好迷茫!
这行得通:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim currContextMenuStrip As New ContextMenuStrip
Me.ContextMenuStrip = currContextMenuStrip
AddHandler currContextMenuStrip.Opening, AddressOf ContextMenuStrip1_Opening
'add a dummy item
Dim newMenuItem As New ToolStripMenuItem
newMenuItem.Text = "dummy"
currContextMenuStrip.Items.Add(newMenuItem)
End Sub
Private Sub ContextMenuStrip1_Opening(sender As Object, e As CancelEventArgs)
Dim currContextMenuStrip As ContextMenuStrip = sender
Dim menuTxt As String = "&Find"
'only add the menu if it doesn't already exist
If (From f In currContextMenuStrip.Items Where f.text = menuTxt).Count = 0 Then
Dim newMenuItem As New ToolStripMenuItem
newMenuItem.Text = menuTxt
currContextMenuStrip.Items.Add(newMenuItem)
End If
'hide the dummy item
Dim items As List(Of ToolStripMenuItem) = (From f As ToolStripMenuItem In currContextMenuStrip.Items Where f.Text = "dummy").ToList
items.First.visible = False
End Sub
End Class
【问题讨论】:
-
你应该设置
Option Strict On,解决出现的问题,然后描述这段代码的作用:你有一个新声明的(empty)ContextMenuStrip,然后即时附加一个新的 ToolStripMenuItem(在显示 empty 菜单时,顺便说一句,没有任何用于选择的事件处理程序)。当然,下次显示 ContextMenuStrip 时会显示 MenuItem。 -
Option Strict显然是Off,因为您到处都有后期绑定。当然你不能这样做:Dim currContextMenuStrip As ContextMenuStrip = sender(你不应该)使用选项On。这是处理 ContextMenuStrip 的一种非常奇怪的方式。你真的需要在每次打开菜单时检查你是否添加了那些 MenuItems 吗?为什么不设置一个根据您设置的条件添加和删除 MenuItems 的过程(如果设置了条件,从这段代码中不清楚为什么此时要添加 MenuItem) -
“好困惑”。我似乎很清楚发生了什么。这是一个优化。假设您有一个盒子,并且您知道盒子是空的。如果有人让你把盒子里的所有东西都倒在桌子上,你会经历打开盒子然后把它倒过来的游戏,结果什么都没有掉出来吗?当然不是。你只是告诉他们盒子是空的,什么也不做。这就是这里发生的事情。系统知道菜单是空的,没有什么可显示的,所以它不会尝试。
-
“有点过分热心”。可能是这样。也许这是该优化的意外结果,但这不会改变意图或实施。你几乎已经找到了你的解决方法,所以去吧。如果这不方便,因为这意味着您不能简单地测试计数,那么还有很多其他选择。您可以只使用
Boolean字段来指示菜单是否已初始化,或者您可以派生自己的自定义类,例如自动添加一个虚拟项目并设置一个只读标志,当从外部添加项目时该标志会重置。 -
建议: 在设计时或
Load事件中添加您需要的所有项目,然后在Opening事件中根据当前条件切换可见性。或者,在设计时添加默认项,然后返回代码中应替换ContextMenuStrip的项并从那里添加/删除。应该在某些地方执行此操作,例如SelectedIndexChanged事件,或者选定的选项卡已更改...等。没有明确的上下文告诉你在哪里。除了Opening事件之外的其他地方。
标签: vb.net winforms contextmenustrip