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

编辑:刚刚发现这似乎与上下文栏在第一次右键单击时没有任何项目有关。如果我添加一个虚拟项目,然后在添加其他项目后隐藏它,它会在第一次右键单击时起作用。所以困惑!

如此:

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

如果您真的需要这样做,一个选择是创建您自己的自定义ContextMenuStrip,它在没有项目和对虚拟项目的需求时解释行为。我使用了以下代码:

Imports System.ComponentModel
Public Class Form1
Private WithEvents menu As New ContextMenuStrip
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ContextMenuStrip = menu
End Sub
Private Sub menu_Opening(sender As Object, e As CancelEventArgs) Handles menu.Opening
If menu.Items.Count = 0 Then
menu.Items.AddRange({New ToolStripMenuItem("First"),
New ToolStripMenuItem("Second"),
New ToolStripMenuItem("Third")})
End If
End Sub
Private Sub menu_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles menu.ItemClicked
MessageBox.Show(e.ClickedItem.Text)
End Sub
End Class

看到了与您描述的相同的行为。然后定义这个类:

Public Class ContextMenuStripEx
Inherits ContextMenuStrip
Private dummyItem As ToolStripItem
Public ReadOnly Property IsInitialised As Boolean
Get
Return dummyItem Is Nothing
End Get
End Property
Public Sub New()
dummyItem = Items.Add(CStr(Nothing))
End Sub
''' <inheritdoc />
Protected Overrides Sub OnItemAdded(e As ToolStripItemEventArgs)
If Not IsInitialised Then
Items.Remove(dummyItem)
dummyItem = Nothing
End If
MyBase.OnItemAdded(e)
End Sub
End Class

并将我的表单代码更改为:

Imports System.ComponentModel
Public Class Form1
Private WithEvents menu As New ContextMenuStripEx
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ContextMenuStrip = menu
End Sub
Private Sub menu_Opening(sender As Object, e As CancelEventArgs) Handles menu.Opening
If Not menu.IsInitialised Then
menu.Items.AddRange({New ToolStripMenuItem("First"),
New ToolStripMenuItem("Second"),
New ToolStripMenuItem("Third")})
End If
End Sub
Private Sub menu_ItemClicked(sender As Object, e As ToolStripItemClickedEventArgs) Handles menu.ItemClicked
MessageBox.Show(e.ClickedItem.Text)
End Sub
End Class

并按预期工作。注意,最后一个代码片段使用了自定义类型及其自定义属性。

感谢所有的帮助和建议!我最终决定在Designer中构建菜单的超集,然后在运行时显示/隐藏。这样每次右键都比每次重新创建菜单要快。

Microsoft有旧样式和新样式上下文菜单。Popup事件用于旧风格的上下文菜单,它接收一个普通的EventArgs对象。新的上下文菜单使用open事件,它接收一个CancelEventArgs对象。如果currContextMenuStrip。Items不包含任何项,e.Cancel在调用事件处理程序时将被设置为True(这导致了您遇到的问题)。修复方法是添加菜单项,然后将e.Cancel设置为False。之后应该会显示良好。为了确保项确实被添加,e.Cancel的赋值可以用if语句来保护,如下所示:

If currContextMenuStrip.Items.Count <> 0 Then
e.Cancel = False
End If

最新更新