TreeView Double Click and canceling expansion

Does anyone know of a way to cancel the node expansion on double click in a treeview   I can't seem to figure it out, it seems that the events happen in an order that does not allow me to do this, has anyone figured out a workaround

Thanks,

paul Tyng


Answer this question

TreeView Double Click and canceling expansion

  • Cynthia Joffrion

    Hello Leonard Gambrell Here

    I used the nodes boundary along with the previuosly captured mousedown point. I couldn't get a consistant behavior with the time/ticks because I had processes in the AfterSelect event that affected the ticks difference.

    The bounds works pretty good because the x value starts right at the text of the current node
    I used this in a commercial project at SmartOutline.com



        Private IsDoubleClick As Boolean = False
        Dim MDown As New Point


     Private Sub trView_MouseDown(ByVal z As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles trView.MouseDown

             IsDoubleClick = (MDown.X = e.X And MDown.Y = e.Y) 
             MDown = New Point(e.X, e.Y)

     End Sub

        Private Sub trView_BeforeExpand(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles trView.BeforeExpand

            If IsDoubleClick AndAlso e.Action = TreeViewAction.Expand Then
                e.Cancel = MDown.X > e.Node.Bounds.X - 19
            End If
            IsDoubleClick = False

        End Sub

        Private Sub trView_BeforeCollapse(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles trView.BeforeCollapse

            If IsDoubleClick AndAlso e.Action = TreeViewAction.Collapse Then
                e.Cancel = MDown.X > e.Node.Bounds.X - 19
            End If
            IsDoubleClick = False

        End Sub

  • itai_sh100

    This should fix the problems, works nicely for me.

    #Region "DoubleClick-expand restriction hack"
        Private m_FirstMouseDownTime As Long
        Private blnDoubleClick As Boolean = False
        Private Sub tv_BeforeExpand(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles tv.BeforeExpand
            If blnDoubleClick AndAlso e.Action = TreeViewAction.Expand Then
                e.Cancel = True
            Else
                m_FirstMouseDownTime = 0
            End If
        End Sub

        Private Sub tv_BeforeCollapse(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles tv.BeforeCollapse
            If blnDoubleClick AndAlso e.Action = TreeViewAction.Collapse Then
                e.Cancel = True
            Else
                m_FirstMouseDownTime = 0
            End If
        End Sub

        Private Sub tv_MouseDown(ByVal sender As Object, _
                                 ByVal e As System.Windows.Forms.MouseEventArgs) _
                                 Handles tv.MouseDown
            If Now.Ticks - m_FirstMouseDownTime <= (SystemInformation.DoubleClickTime * TimeSpan.TicksPerMillisecond) Then
                blnDoubleClick = True
            Else
                blnDoubleClick = False
            End If
            m_FirstMouseDownTime = Now.Ticks
        End Sub
    #End Region

  • smcleod

    Silly question but is there anything wrong with 

    Private mbIsDoubleClick As Boolean = False

    Protected Overrides Sub OnBeforeExpand(ByVal e As System.Windows.Forms.TreeViewCancelEventArgs)
       If mbIsDoubleClick Then
          e.Cancel = True
          Exit Sub
       End If
    End Sub

    Protected Overrides Sub OnBeforeCollapse(ByVal e As System.Windows.Forms.TreeViewCancelEventArgs)
       If mbIsDoubleClick Then
          e.Cancel = True
          Exit Sub
       End If
    End Sub

            Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
                mbIsDoubleClick = e.Clicks > 1
            End Sub

    Geniune question btw as this is what I'm using in mine!

  • Will Harris

    I understand what you are saying and see the dilemma.  This is definitely a "tricky" thing.  Here is some alternative code that works better but is still not without problems.  I'll explain the problems after the code listing.

        Private m_FirstMouseDownTime As Long
        Private blnDoubleClick As Boolean = False
        Private Sub TreeView1_BeforeExpand(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles TreeView1.BeforeExpand
            If blnDoubleClick Then
                If e.Action = TreeViewAction.Expand Then
                    e.Cancel = True
                End If
            End If
        End Sub

        Private Sub TreeView1_BeforeCollapse(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles TreeView1.BeforeCollapse
            If blnDoubleClick Then
                If e.Action = TreeViewAction.Collapse Then
                    e.Cancel = True
                End If
            End If
        End Sub

        Private Sub TreeView1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TreeView1.MouseDown
            If Now.Ticks - m_FirstMouseDownTime <= (SystemInformation.DoubleClickTime * TimeSpan.TicksPerMillisecond) Then
                blnDoubleClick = True
            Else
                blnDoubleClick = False
            End If
            m_FirstMouseDownTime = Now.Ticks
        End Sub


    Two problems with this code:
    1-  Double-clicking on the "+/-" signs do not process.  Single-clicks do, however.  
    2-  Clicking on the node and then clicking on the "+/-" sign with nearly zero interval does not process correctly.  (This is simply an extension of the first problem).

    Unfortunately, there is no Treeview Style to prevent this nor no message or notification for this particular scenario.

  • Sathya_Subbu

    It is a good starting point, thanks, I will try to debug it on my own, but here is the repro steps and the methods fired with mouse down counts:

    1. Click a node
    2. wait a few seconds (internal mouse down count is 1)
    3. double click the same node (first click count = 2, second click count is reset to 0)

    Straight from my output window:

    Mouse Down Count: 0
    Method: OnMouseDown
    Mouse Down Count: 1
    Method: OnClick
    Method: OnBeforeSelect
    Method: OnAfterSelect
    Method: OnMouseDown
    Mouse Down Count: 2
    Method: OnClick
    Method: OnMouseDown
    Mouse Down Count: 0
    Method: OnBeforeExpand
    Mouse Down Count: 0
    Method: OnAfterExpand
    Method: OnDoubleClick

    Also the code is not node specific, I already have an inherited tree view i wrote that forwards tree events to the node they are happening on, so they can maintain their counts internally.  I think the biggest issue is determining when to reset state.  I almost need to have the windows time between clicks and click point difference threshold settings internally to calculate whether its a double click or not. 

    I have done a lot of playing with this, despite the brevity of my original post I have tried basically every option I can think of to do this, including this one of counting clicks.  I tried your code again just to verify that I wasn't doing something wrong.  There are almost too many scenarios to account for for me to reliably determine that it is in fact a double click before the double click fires.  If you know of some way to take basically two points from two consecutive mouse down events and the time between them and calculate whether or not it was a double click thats probably what i need.

  • Bevin R Brett

    I can't accurately reproduce the issue you are seeing without some more detailed steps.  However, the BeforeSelect event occurs after the BeforeExpand event.  Feel free to play around with the code and let us know if you come up with a solution.  If you want, you can provide some more detailed steps to reproduce the issue and I'll look it when I have some time.  Regardless, though, the code I provided should be a solid starting point for you.
  • davidwdf

    Jacob to the rescue!  nice!  ;) 
  • Kressilac

    Thanks!

    That is exactly what I needed.  I put in the code to do the point comparison but that is a minor change.  I shoudl have figured it was this easy to find the double click information, I just neglected to search thoroughly.  

    The +/- behavior is unwanted but acceptable,  in the future I can possibly figure out the root line and +/- box sizing and put that in the to calculation as well, but for now I am done.

    Thanks again,

    Paul Tyng

  • Sheng Jiang

    Thanks a lot! But i have noticed one issue...

    If I click once on a node somewhere, then double click a little later on that same node, it pops up and expands, have any input on to how I can fix that

    I'm not sure where the select event is in that event sequence but maybe I should reset the mousedown count in the select event or something to that effect

    Thanks,

    Paul Tyng

  • Rudolf Dvoracek

    Well, the sequence of events that occurs with DoubleClick expanding or collapsing looks like this:

    MouseDown
    Click
    MouseUp
    MouseDown
    BeforeExpand/BeforeCollapse
    DoubleClick
    MouseUp

    The BeforeExpand/BeforeCollapse events recieve a TreeViewCancelEventArgs parameter that allows you to cancel the action.  Based on the event sequence above, you should be good to go with counting the MouseDown events.  This appears to work:

        Private m_MouseDownCount As Integer = 0
        Private Sub TreeView1_BeforeExpand(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles TreeView1.BeforeExpand
            If m_MouseDownCount = 2 Then
                If e.Action = TreeViewAction.Expand Then
                    e.Cancel = True
                End If
            End If
            m_MouseDownCount = 0
        End Sub

        Private Sub TreeView1_BeforeCollapse(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) Handles TreeView1.BeforeCollapse
            If m_MouseDownCount = 2 Then
                If e.Action = TreeViewAction.Collapse Then
                    e.Cancel = True
                End If
            End If
            m_MouseDownCount = 0
        End Sub

        Private Sub TreeView1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TreeView1.MouseDown
            m_MouseDownCount = ((m_MouseDownCount + 1) Mod 3)
        End Sub


    Let me know if you have any questions.

  • Bassam Mansoob

    Hi,

     Just 2 fixes for this very good code that helped me to write an extended treeview class in C# :

      After each e.Cancel = true, you must set blnDoubleClick to false. If not, all the expand or collapse commands will be cancelled after a double clic on the treeview.

      To avoid problems, you can compare in MouseDown the coordinates of the last click with the previous one. If they are equal, and Now.Ticks - m_FirstMouseDownTime <= (SystemInformation.DoubleClickTime * TimeSpan.TicksPerMillisecond), then you set blnDoubleClick to true.

      Now you are sure that the user has doubleclicked on a unique node.


    Phoennix

  • Mark Staples

    did you try the BeforeExpand Event   the "e" parameter has a Cancel Property you can set to True
  • TreeView Double Click and canceling expansion