Wpf treeviewitem mouse double click

I'm having trouble identifying the selected TreeViewItem; I have the following structure in a tree structure:

 + Module 1 (name k1)
   - Sub Module 1 (name s1)
 + Module 2 (name k2)
   - Sub Module 2 (name s2)
 + Module 3 Name (k3)
   - Sub Module 3 (name s3)
   - Sub Module 4 (name s4)

      

Me xaml:

<TreeView x:Name="treview_Menu">
   <TreeView.ItemContainerStyle>
      <Style TargetType="{x:Type TreeViewItem}">
         <EventSetter Event="MouseDoubleClick" Handler="OnItemMouseDoubleClick" />
      </Style>
   </TreeView.ItemContainerStyle>
</TreeView>

      

In the code I have this:

Private Sub OnItemMouseDoubleClick(sender As Object, args As MouseButtonEventArgs)
   MsgBox(sender.name)
End Sub

      

in the above code always returns the name of the top node, for example if I double click on sub_module 3 o sub_module 4 always returns the name of Module_3, the same happens with sub_module 1 and sub_module 2 ... as can I fix this?

+3


source to share


1 answer


The problem I believe is that it ItemContainerStyle

only applies to the first level of nodes (this, in my opinion, has to do with what inherits from ItemsControl

and the ItemContainerStyle

way of inheritance TreeView

) where this is true to the main one Items

ItemsControl

. Anyway, I'm leaving for one ...)

You can fix this, instead of assigning a style ItemContainerStyle

, just move it to Resources

, for example:

<TreeView.Resources>
    <Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
        <EventSetter Event="MouseDoubleClick" Handler="OnItemMouseDoubleClick"/>
    </Style>
</TreeView.Resources>

      

Depending on what you want, this may not work the way you plan ...

As this adds a trigger for each TreeViewItem - and unfortunately they are nested like this:

        <TreeViewItem Header="Module 1">
            <TreeViewItem Header="Sub Module 1"/>
        </TreeViewItem>
        <TreeViewItem Header="Module 2">
            <TreeViewItem Header="Sub Module 1"/>
            <TreeViewItem Header="Sub Module 2"/>
        </TreeViewItem>

      

So, depending on what you are going to use the code for, there might be a problem that the event is fired for both the outer and inner module.

The usual way to deal with this ClickEvent

is to set args.Handled

in True

code to stop the bubble event to higher levels. Unfortunately, this doesn't work in events MouseDoubleClick

because of the way they fire. (Good Microsoft ... xD)

A possible answer instead : fooobar.com/questions/321500 / ...



Basically, we don't use an event MouseDoubleClick

and instead use an event PreviewMouseLeftButtonDown

(which Microsoft uses to fire the event MouseDoubleClick

, obviously). Anyway, we can run it like this:

(Please excuse C #, I tried to answer this in terms of wpf, but I don't know the equivalent VB code)

OnItemPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)   {
    if (e.ClickCount == 2) {
        e.Handled = true;
        var treeViewItem = sender as TreeViewItem;
        MessageBox.Show(treeViewItem.Header.ToString());
    }
}

      

HOWEVER, because the preview event tunnels down, it unfortunately fires once on the containing element and not on the containing element, so we'll go back to square 1. We could peek in args.OriginalSource

here, but we're basically getting into the scene. where another solution is appropriate:

Separate alternative

A separate alternative is to simply add an event listener to the integer TreeView

in its double click event, which then just finds where TreeViewItem

it is OriginalSource

. (If you want to handle it and stop pushing it / trigger other effects, you need to intercept the event instead PreviewMouseLeftButtonDown

, as above).

To do this, you can take MouseButtonEventArgs args

and consider args.OriginalSource

(this is the topmost element in the visual tree that you clicked on), and then you have several cases: either it is not inside any TreeViewItem

at all, or it itself is the TreeViewItem

one you need, or the third the possibility is that the OriginalSource is an element somewhere inside TreeViewItem

that you want (this is the most likely case - from testing, you usually click on the a TextBlock

contained within TreeViewItem

), in which case you can recursively find the parents until you click on the first parent of the type TreeViewItem

. (You can do this using the method VisualTreeHelper

GetParent

.)

Basically, the above algorithm can be summed up as just recursively checking the current element to see if it is of type TreeViewItem

or TreeView

else you make the current element its parent and recursion ... If you end with TreeViewItem

, you have the required element, otherwise if you click on it outside the element, you will be on TreeView

.

PS: Since I cannot write VB, I think that explaining the above algorithm is probably better than trying to write it, but I hope that the above explanations will still be helpful to you :)

+4


source







All Articles