ContextMenuStrip 需要两次右键才能显示

时间:2021-01-22 02:12:03

标签: vb.net winforms contextmenustrip

我喜欢以编程方式创建我的上下文菜单。我通常不会将项目添加到上下文菜单条,直到它打开,因为显示的项目取决于设计的其他可变方面。

我发现上下文菜单条似乎需要两次右键单击才能显示。我尝试在不同的事件(打开、打开等)中添加菜单项,并手动将 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

2 个答案:

答案 0 :(得分:2)

如果您确实需要以这种方式做事,一种选择是创建您自己的自定义 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

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

答案 1 :(得分:1)

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

相关问题