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?
source to share
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 :)
source to share