Event handled by TreeView.SelectedItemChanged still bubbling

I have a TreeView connected to a hierarchy consisting of several different classes through HierarchicalDataTemplate s. When an item in the tree is selected, the SelectedItemChanged event, of course, happily bubbles up through the parent elements, as it should. What he should not do, but still do, happily continues to bubble after I set e.Handled to true .

The event will still fire on the parent, and RoutedPropertyChangedEventArgs will look exactly like the parent; even the OriginalSource property points to the parent, not the one that was originally selected. e.Handled , of course, will be false .

The very same question was asked here , but I do not use EventAggregator or CAL, and the workaround found here does not help, because I am not specifically after the mouse event.

Is there any way to accurately get the item that was actually selected, or to force stop bubbling madness (without resorting to very cruel and unethical hacking using global variables that I can think of)?

Thanks for any ideas.

+6
source share
2 answers

After reading Rick's answer, I talked to an employee who, as it turned out, had the same problem. I tried different things in my application (discovery: the TreeViewItem.Selected event behaves just the same wrong) and the test project, and found that in the test application the events fired exactly as expected. Thus, a significant difference in the environment (the XAML and ViewModel classes were almost identical), which led to this difference in behavior - and the culprit looks like COM, precisely placing WPF controls in the COM application.

My colleague's application is a Word extension using VSTO, and my VSPackage for Visual Studio 2010 - both Word and VS2010 are still the main code. On the other hand, my test application is, of course, a small simple WPF project. I added a WinForms form with ElementHost, which in turn hosted a UserControl with a TreeView, but still worked as it should, so for me it really looks like the host COM application is somehow interfering with events raised on the TreeView and TreeViewItems.

Fortunately, my colleague found a / googled solution that will currently be done - after you finish with a real reaction to the event, at the end of the event handler method again set TreeViewItem as the selected and concentrated one:

 item.Focus(); item.IsSelected = true; 

We don’t understand why, but this will stop re-fetching elements (this is clearly not a bubbling event in the sense of WPF).

Thanks again to Rick for pushing me to keep the TreeView and TreeViewItem events in mind.

+2
source

Your question puzzles me because the SelectedItemChanged event is a TreeView event, not a TreeViewItem event. "Hey man, my event was far from your event!"

When the selected item changes, the TreeView raises the SelectedItemChanged event on , TreeView , and if it is raw, it begins to pop up to the root element of the page.

Writing a small test program helps when you need proof.

Here's the little TreeView contained in the Grid :

 <Grid TreeView.SelectedItemChanged="Grid_SelectedItemChanged"> <TreeView SelectedItemChanged="TreeView_SelectedItemChanged"> <TreeViewItem TreeView.SelectedItemChanged="TreeViewItem_SelectedItemChanged" Header="Item1"> <TreeViewItem TreeView.SelectedItemChanged="TreeViewItem_SelectedItemChanged" Header="Item2"> <TreeViewItem TreeView.SelectedItemChanged="TreeViewItem_SelectedItemChanged" Header="Item3"/> </TreeViewItem> </TreeViewItem> </TreeView> </Grid> 

and here is the code for the test:

 private void Grid_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) { SelectedItemChanged(sender, e, "Grid"); } private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) { SelectedItemChanged(sender, e, "TreeView"); e.Handled = true; } private void TreeViewItem_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) { SelectedItemChanged(sender, e, "TreeViewItem"); } private void SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e, string handler) { Debug.WriteLine(""); Debug.WriteLine(string.Format("SelectedItemChanged: handler = {0}", handler)); Debug.WriteLine(string.Format("e.NewValue.Header = {0}", (e.NewValue as TreeViewItem).Header)); Debug.WriteLine(string.Format("sender = {0}", sender)); Debug.WriteLine(string.Format("e.Source = {0}", e.Source)); Debug.WriteLine(string.Format("e.OriginalSource = {0}", e.OriginalSource)); } 

and running it and clicking on the first element, you get this debug output:

 SelectedItemChanged: handler = TreeView e.NewValue.Header = Item1 sender = System.Windows.Controls.TreeView Items.Count:1 e.Source = System.Windows.Controls.TreeView Items.Count:1 e.OriginalSource = System.Windows.Controls.TreeView Items.Count:1 

which shows that the event is raised on the TreeView itself and setting e.Handled to true prevents the Grid event from being received. Comment on the row coming out and it bubbles up to the Grid .

But in no case does the TreeViewItem a SelectedItemChanged handler.

Try using small test programs if something is not what you think. It’s much easier to do experiments and get to the bottom of the problem!

+2
source

Source: https://habr.com/ru/post/888956/


All Articles