3
votes

The default behavior of Winforms treeview is to check/uncheck a node only when the checkbox is clicked. I want to implement a treeview that will also toggle the check state if the node text is clicked (user editing of node text is disabled).

The nature of the treeview events are making this more difficult than it seems it should be. My initial approach was to inherit the treeview, override the node mouse click event, and suppress the default treenode check behavior (since I am checking the node myself, if I didn't suppress it would result in a double-check when the mouse click was actually on the node checkbox):

 Private _SuppressCheck As Boolean = False

 Protected Overrides Sub OnBeforeCheck(e As System.Windows.Forms.TreeViewCancelEventArgs)
        If _SuppressCheck Then e.Cancel = True
        MyBase.OnBeforeCheck(e)
    End Sub

    ''' <summary>
    ''' Enables node checking for click on any part of node.
    ''' </summary>
    Protected Overrides Sub OnNodeMouseClick(e As System.Windows.Forms.TreeNodeMouseClickEventArgs)
        Try
            If e.Button = Windows.Forms.MouseButtons.Left Then
                e.Node.Checked = Not e.Node.Checked
                _SuppressCheck = True
            End If
            MyBase.OnNodeMouseClick(e)
        Finally
            _SuppressCheck = False
        End Try
    End Sub

However there are at least two big problems with this. Number one, the OnBeforeCheck fires before OnNodeMouseClick (which I don't understand because it's the mouse click that causes the check change), so I really am not suppressing anything.

Number two, the NodeMouseClick will fire even for clicks on the Open\Close glyph, and obviously I don't want to change the check state for that. But the NodeClick event args do not specify which part of the node (open/close, text, or checkbox) was clicked. How can I devise a less buggy method of checking nodes on text click?

1

1 Answers

3
votes

You can just check the Bounds property:

Protected Overrides Sub OnNodeMouseClick(e As TreeNodeMouseClickEventArgs)
  MyBase.OnNodeMouseClick(e)
  If e.Button = MouseButtons.Left AndAlso _
     e.Node.Bounds.Contains(New Point(e.X, e.Y)) Then
    e.Node.Checked = Not e.Node.Checked
  End If
End Sub