0

I am attempting to create a TreeView control with custom TreeNode. Each TreeNode has an associated custom type/category which defines the appearance (eg, colour) and a specific right-click context menu. I’ve managed to construct the TreeView but having difficulty in working out how to handle the Context Menu Item click event.

The following code gives an example of how I’ve constructed the TreeView. I simply have a form with a TreeView Control (TreeView1) and the custom TreeNode class (clsTreeviewNode). There’s a structure “NodeType” which is passed to the custom TreeNode and which, in this example, is used to define the colour and Context Menu items for each node

For this example I’m simply capturing the event in clsTreeviewNode and displaying the Node Name and Context Menu Item with a MessageBox call. However, I need to work out how I can process the event in the main code in the form. Hence, I need to be able to raise an event in clsTreeviewNode and pass it to the form with the relevant parameters.

I’m assuming that I may have to generate a custom TreeView class but cannot work out how to process the events and handlers etc from the collection of nodes within the TreeView.

Form Class:

Public Enum NodeType
    Type0
    Type1
    Type2
End Enum


Public Class Form1

    Private myNode As clsTreeviewNode

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        myNode = New clsTreeviewNode(NodeType.Type0, "Root 1")
        TreeView1.Nodes.Add(myNode)
        myNode.Nodes.Add(New clsTreeviewNode(NodeType.Type1, "Item 1"))
        myNode.Nodes.Add(New clsTreeviewNode(NodeType.Type1, "Item 2"))

        myNode = New clsTreeviewNode(NodeType.Type0, "Root 2")
        TreeView1.Nodes.Add(myNode)
        myNode.Nodes.Add(New clsTreeviewNode(NodeType.Type2, "Item 3"))
        myNode.Nodes.Add(New clsTreeviewNode(NodeType.Type2, "Item 4"))

    End Sub

End Class

Custom TreeNode:

Public Class clsTreeviewNode

    Inherits TreeNode

    Private WithEvents cmContextMenu As New ContextMenuStrip

    Public Sub New(ByVal NodeType As NodeType, ByVal Text As String)
        Me.Text = Text
        Select Case NodeType
            Case NodeType.Type0
                Me.ForeColor = Color.DarkGreen
                'TYpe0 has no context menu
            Case NodeType.Type1
                Me.ForeColor = Color.DarkBlue
                With cmContextMenu
                    .Items.Add("Menu a")
                    .Items.Add("Menu b")
                End With
                Me.ContextMenuStrip = cmContextMenu
            Case NodeType.Type2
                Me.ForeColor = Color.DarkRed
                With cmContextMenu
                    .Items.Add("Menu c")
                    .Items.Add("Menu d")
                    Me.ContextMenuStrip = cmContextMenu
                End With
        End Select
    End Sub

    Private Sub ContextMenuItem_Click(sender As Object, e As ToolStripItemClickedEventArgs) Handles cmContextMenu.ItemClicked
        'Messagebox just demonstrating that the ConextMenuItemClick is handled
        'I want to raise an event that can be handled within the form
        MessageBox.Show(String.Format("Node Selected: {1}{0}Menu Item Clicked: {2}", vbCrLf, Me.Text, e.ClickedItem.ToString))
    End Sub

End Class

1 Answer 1

0

So I've got something working as I want, and it looks fairly neat, but I'm not sure if it's the right way to do it. It uses a sort of Call-Back (I think that's the right term!).

I've created a custom TreeView (clsTreeView) to which I've added an event to pass up to the form. I've put a method in clsTreeView (CatchTreeNodeContextMenuClickEvent) which raises the event.

And when a ContextMenu event is raised within the Custom TreeNode (clsTreeviewNode), I then call the CatchTreeNodeContextMenuClickEvent method in clsTreeView (ie, I do not generate a custom event from the custom TreeNode).

I would still like to know if it's possible to actually raise a custom event within the clsTreeviewNode which I can then trap in clsTreeView. My main concern is whether the following line has any undesirable effects:

CType(Me.TreeView, clsTreeView).CatchTreeNodeContextMenuClickEvent(Me.Text, e.ClickedItem.ToString)

In the actual application I'm writing, there will be a lot of navigation around the treeview with various nodes being cleared and nodes added. What I don't know is, if you clear all the sub-nodes from a node, will all those sub-node classes be correctly disposed of automatically (ie, all the appropriate garbage collection taking place).

The example code is:

Form:

Public Enum NodeType
    Type0
    Type1
    Type2
End Enum

Public Class Form1

    Private WithEvents TreeView1 As New clsTreeView
    Private myNode As clsTreeviewNode

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Me.Controls.Add(TreeView1)
        With TreeView1
            .Top = 0
            .Left = 0
            .Width = Me.ClientSize.Width
            .Height = Me.ClientSize.Height
            .Anchor = AnchorStyles.Left + AnchorStyles.Right + AnchorStyles.Top + AnchorStyles.Bottom
        End With

        myNode = New clsTreeviewNode(NodeType.Type0, "Root 1")
        TreeView1.Nodes.Add(myNode)
        myNode.Nodes.Add(New clsTreeviewNode(NodeType.Type1, "Item 1"))
        myNode.Nodes.Add(New clsTreeviewNode(NodeType.Type1, "Item 2"))

        myNode = New clsTreeviewNode(NodeType.Type0, "Root 2")
        TreeView1.Nodes.Add(myNode)
        myNode.Nodes.Add(New clsTreeviewNode(NodeType.Type2, "Item 3"))
        myNode.Nodes.Add(New clsTreeviewNode(NodeType.Type2, "Item 4"))

    End Sub


    Private Sub TreeView1_ContextMenuClickEvent(NodeName As String, MenuItem As String) Handles TreeView1.ContextMenuClickEvent
        MessageBox.Show(String.Format("Node Selected: {1}{0}Menu Item Clicked: {2}", vbCrLf, NodeName, MenuItem))
    End Sub

End Class

Custom TreeView:

Public Class clsTreeView

    Inherits TreeView

    Public Event ContextMenuClickEvent(NodeName As String, MenuItem As String)

    Public Sub CatchTreeNodeContextMenuClickEvent(NodeName As String, MenuItem As String)
        RaiseEvent ContextMenuClickEvent(NodeName, MenuItem)
    End Sub

End Class

Custom TreeNode:

Public Class clsTreeviewNode

    Inherits TreeNode

    Private WithEvents cmContextMenu As New ContextMenuStrip

    Public Sub New(ByVal NodeType As NodeType, ByVal Text As String)
        Me.Text = Text
        Select Case NodeType
            Case NodeType.Type0
                Me.ForeColor = Color.DarkGreen
                'TYpe0 has no context menu
            Case NodeType.Type1
                Me.ForeColor = Color.DarkBlue
                With cmContextMenu
                    .Items.Add("Menu a")
                    .Items.Add("Menu b")
                End With
                Me.ContextMenuStrip = cmContextMenu
            Case NodeType.Type2
                Me.ForeColor = Color.DarkRed
                With cmContextMenu
                    .Items.Add("Menu c")
                    .Items.Add("Menu d")
                    Me.ContextMenuStrip = cmContextMenu
                End With
        End Select
    End Sub

    Private Sub ContextMenuItem_Click(sender As Object, e As ToolStripItemClickedEventArgs) Handles cmContextMenu.ItemClicked
        CType(Me.TreeView, clsTreeView).CatchTreeNodeContextMenuClickEvent(Me.Text, e.ClickedItem.ToString)
    End Sub

End Class
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.