I have created a ContextMenuStrip with three different items. Then I have a TreeView with a parent and child nodes. I assigned the ContextMenuStrip to both nodes like so:
fatherNode.ContextMenuStrip = menuNodes
childNode.ContextMenuStrip = menuNodes
The problem is that the items from the menu must perform different actions depending on which node calls the menu item. In other words, for example if the first item on the menu is "create", it will create something very specific if the father node calls it and a different thing if the child calls the same menu item.
Hopefully I was able to explain what I mean and sorry I do not have any code because I have no clue how I can achieve this.
Suppose you have two methods:
Private Sub ParentNodeMethod()
Console.WriteLine("Parent Node Method")
End Sub
Private Sub ChildNodeMethod()
Console.WriteLine("Child Node Method")
End Sub
... and you have a ContextMenuStrip for a TreeView control and you want a specific menu strip item (ToolStripMenuItem) calls - on click - one of them according to which TreeNode is clicked.
You could utilize the 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 event of the ContextMenuStrip to invoke it.
Replace you code with:
'//
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
Another way is to create a Dictionary(Of TreeNode, Action)
instead of assigning the actions to the Tag
properties:
'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
Alternatively and as already mentioned by @Jimi, if the TreeNode objects of the same Level should call the same method, then use this property to decide which method should be called.