Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Test if a TreeNode was actually clicked

4.95/5 (10 votes)
20 Nov 2013CPOL2 min read 25.1K  
Test if a TreeNode was expanded or collapsed rather than actually clicked.

Introduction

I'm working on a project manager type of application with a pretty straightforward design: projects and their constituent steps are read from the database and displayed hierarchically as nodes in a TreeView control. Clicking on a project or step node retrieves the details and generates a tab in an adjoining TabControl. This was being handled by intercepting the tree's NodeMouseClick event and was working great.

The problem was that expanding or collapsing a project node also triggered NodeMouseClick. I needed to figure out how to perform my action when the node was actually clicked, and not when the expand / collapse bullet next to the node was clicked.

The blindingly obvious solution

I spent a while searching the web and trying the offered solutions. All were along the lines of "intercept an earlier event, test to see what happened, then set a global variable that will be read in a later event." None of these solutions could be adapted to what I needed. So I started poking around and found the solution in the event's own parameter.

NodeMouseClick receives TreeNodeMouseClickEventArgs. This class contains Node, which gives the tree node that was clicked, and Location, which gives the mouse's position relative to the tree's client space when the click occurred. Tree nodes have a property, Bounds, which gives the node's rectangle coordinates relative to the tree view. A quick test verified that the expand / collapse bullet is outside the node's boundary. So I added

VB.NET
e.Node.Bounds.Contains(e.Location)
to my button test in the event and voila! I could perform the action only when the node was really clicked, and not when its collapse state was changing. In VB, this looks like:
VB.NET
Private Sub CurrentTree_NodeMouseClick(ByVal sender As Object, _
ByVal e As TreeNodeMouseClickEventArgs) _
Handles CurrentTree.NodeMouseClick
    If e.Node.Bounds.Contains(e.Location) AndAlso e.Button = Windows.Forms.MouseButtons.Left Then
        'Code to load project details and generate a tab
    End If
End Sub
In C#:
void CurrentTree_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
    if (e.Node.Bounds.Contains(e.Location) && e.Button == MouseButtons.Left)
    {
        // Code to load project details and generate a tab
    }
}

Works like a charm, at least with .Net 3.5. I don't expect it would be different with any other flavors of the Framework.

Update 1: Made some minor grammar changes, clarified a few points, and added a C# example. I mostly use VB, so please let me know if the C# code is off.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)