通过ContextMenuStrip.Opening事件无效的AddHandler到ToolStripMenuItem

时间:2016-12-21 05:49:21

标签: vb.net winforms

大家好,圣诞快乐。

我最近继承了一个必须添加功能的VB项目。所以我有以下代码:

    Private Sub AddItems()
        Dim itemMenu = DirectCast(ContextMenuStrip.Items.Find("name", False)(0), ToolStripMenuItem)

        For Each dbObject In dbObjects
            Dim item As New ToolStripMenuItem(dbObject.Name)
            item.Tag = dbObject
            AddHandler item.Click, AddressOf Item_Click
            itemMenu.DropDownItems.Add(item)
        Next
    End Sub

    Private Sub RemoveItems()
        Dim itemMenu = DirectCast(ContextMenuStrip.Items.Find("name", False)(0), ToolStripMenuItem)

        For Each item As ToolStripItem In itemMenu.DropDownItems
            RemoveHandler item.Click, AddressOf Item_Click
        Next

        itemMenu.DropDownItems.Clear()
    End Sub

    Private Sub ContextMenuStrip_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ContextMenuStrip.Opening
        AddItems()
    End Sub

    Private Sub ContextMenuStrip_Closing(sender As Object, e As ToolStripDropDownClosingEventArgs) Handles ContextMenuStrip.Closing
        RemoveItems()
    End Sub

    Private Sub Item_Click(sender As Object, e As EventArgs)
        ' Do the work            
    End Sub

逻辑是每次使用有效的数据库对象填充上下文菜单中的子菜单。

问题是此代码不起作用。它将项目完美地添加到上下文菜单中,但AddHandler item.Click, AddressOf Item_Click不执行任何操作。

奇怪的是,如果我在AddItems()中拨打Form_Load,那么它就会完美无缺。

任何帮助都将不胜感激。

2016.12.22 WozzeC回答后的解决方案

    Private Sub AddItems()
        RemoveItems()
        Dim itemMenu = DirectCast(ContextMenuStrip.Items.Find("name", False)(0), ToolStripMenuItem)

        For Each dbObject In dbObjects
            Dim item As New ToolStripMenuItem(dbObject.Name)
            item.Tag = dbObject
            AddHandler item.Click, AddressOf Item_Click
            itemMenu.DropDownItems.Add(item)
        Next
    End Sub

    Private Sub RemoveItems()
        Dim itemMenu = DirectCast(ContextMenuStrip.Items.Find("name", False)(0), ToolStripMenuItem)

        For Each item As ToolStripItem In itemMenu.DropDownItems
            RemoveHandler item.Click, AddressOf Item_Click
        Next

        itemMenu.DropDownItems.Clear()
    End Sub

    Private Sub ContextMenuStrip_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ContextMenuStrip.Opening
        AddItems()
    End Sub

    Private Sub Item_Click(sender As Object, e As EventArgs)
        ' Do the work            
    End Sub

1 个答案:

答案 0 :(得分:1)

我已经玩了一段时间了,我已经成功地重现了你的问题。令人头疼的原因是RemoveItems在Click事件之前触发。因此,当您执行RemoveHandler时,单击事件将消失。

我建议你做的是不在ContextMenuItems上添加点击处理程序。而是在Parent节点上为DropDownItemClicked添加EventHandler。结果将与Item.Click一样工作,但没有动态处理Handler的麻烦。

我还尝试在ContextMenu上为RemoveItems切换Closing到Closed事件。但恐怕无济于事。

解决此问题的另一种方法是将RemoveItems移动到AddItems的第一行。然后删除关闭事件及其对RemoveItems的调用。这意味着无论何时您想要创建新的ContextMenu,前一个都会正确处理。这也将解决您将来添加两次或更多次ContextMenu项目的错误。如果您非常快速地多次右键单击,目前会发生这种情况。