ContextMenuStrip 项根据调用者执行不同的操作

ContextMenuStrip item to perform different actions depending on who calls it

我创建了一个包含三个不同项目的 ContextMenuStrip。然后我有一个带有父节点和子节点的 TreeView。我将 ContextMenuStrip 分配给两个节点,如下所示:

fatherNode.ContextMenuStrip = menuNodes
childNode.ContextMenuStrip = menuNodes

问题是菜单中的项目必须根据调用菜单项的节点执行不同的操作。换句话说,例如,如果菜单上的第一项是 "create",如果父节点调用它,它将创建非常具体的内容,如果子节点调用相同的菜单项,则会创建不同的内容。

希望我能够解释我的意思,抱歉我没有任何代码,因为我不知道如何实现这一点。

假设你有两种方法:

Private Sub ParentNodeMethod()
    Console.WriteLine("Parent Node Method")
End Sub

Private Sub ChildNodeMethod()
    Console.WriteLine("Child Node Method")
End Sub

...并且您有一个用于 TreeView 控件的 ContextMenuStrip,并且您想要一个特定的菜单条项 (ToolStripMenuItem) 调用 - 单击时 - 根据单击的 TreeNode 其中之一。

您可以利用 ContextMenuStrip 的 Action delegate and create different actions that invokes different methods and assign them to the Tag properties of the TreeNode objects in question, handle the TreeView.NodeMouseClick to show the ContextMenuStrip and pass the right action, and handle the ItemClicked 事件来调用它。

将您的代码替换为:

'//
parentNode.Tag = New Action(AddressOf ParentNodeMethod)
childNode.Tag = New Action(AddressOf ChildNodeMethod)
'//

Private Sub TreeView1_NodeMouseClick(sender As Object,
                                     e As TreeNodeMouseClickEventArgs) _
                                     Handles TreeView1.NodeMouseClick

    If e.Button = MouseButtons.Right AndAlso TypeOf e.Node.Tag Is Action Then
        ContextMenuStrip1.Items(0).Tag = e.Node.Tag
        ContextMenuStrip1.Show(TreeView1, e.Location)
    End If
End Sub

Private Sub ContextMenuStrip1_ItemClicked(sender As Object,
                                          e As ToolStripItemClickedEventArgs) _
                                          Handles ContextMenuStrip1.ItemClicked
    If TypeOf e.ClickedItem.Tag Is Action Then
        DirectCast(e.ClickedItem.Tag, Action)()
        e.ClickedItem.Tag = Nothing
    End If
End Sub

另一种方法是创建 Dictionary(Of TreeNode, Action) 而不是将操作分配给 Tag 属性:

'Class member
Private ReadOnly dict As New Dictionary(Of TreeNode, Action)
'//

dict.Add(parentNode, New Action(AddressOf ParentNodeMethod))
dict.Add(childNode, New Action(AddressOf ChildNodeMethod))
'//

Private Sub TreeView1_NodeMouseClick(sender As Object,
                                     e As TreeNodeMouseClickEventArgs) _
                                     Handles TreeView1.NodeMouseClick

    Dim a As Action = Nothing

    If e.Button = MouseButtons.Right AndAlso dict.TryGetValue(e.Node, a) Then
        ContextMenuStrip1.Items(0).Tag = a
        ContextMenuStrip1.Show(TreeView1, e.Location)
    End If
End Sub

Private Sub ContextMenuStrip1_ItemClicked(sender As Object,
                                          e As ToolStripItemClickedEventArgs) _
                                          Handles ContextMenuStrip1.ItemClicked
    If TypeOf e.ClickedItem.Tag Is Action Then
        DirectCast(e.ClickedItem.Tag, Action)()
        e.ClickedItem.Tag = Nothing
    End If
End Sub

或者,正如@Jimi 已经提到的,如果相同 Level 的 TreeNode 对象应该调用相同的方法,则使用此 属性 来决定应该调用哪个方法。