处理的TreeView.SelectedItemChanged事件仍然冒泡

问题描述

| 我有一个TreeView通过
HierarchicalDataTemplate
绑定到由几个不同的类组成的层次结构中。当选择树中的一项时,当然会很高兴地在父项上向上吹起“ 1”事件。我将
e.Handled
设置为
true
之后,它不应该做,但仍然要做的是愉快地冒泡。 该事件仍将在父项上触发,并且
RoutedPropertyChangedEventArgs
看起来与选择的父项完全相同。即使是
OriginalSource
属性也将指向父项,而不是最初选择的项。
e.Handled
当然是
false
。 在这里提出了几乎相同的问题,但是我没有使用
EventAggregator
或CAL,并且在这里找到的解决方法没有太大帮助,因为我不是在发生鼠标事件后才专门进行的。 是否有任何方法可以准确地获取实际选择的物品,或有力地阻止冒泡的疯狂行为(无需借助我能想到的全局变量求助于非常暴力和不道德的黑客行为)? 感谢您的任何见解。     

解决方法

您的问题使我感到困惑,因为
SelectedItemChanged
事件是
TreeView
事件,而不是
TreeViewItem
事件。 “嘿,我的活动离您的活动不远了!” 当所选项目更改时,
TreeView
本身将引发
SelectedItemChanged
事件,即
TreeView
,如果未处理,它将开始向页面的根元素冒泡。 编写小型测试程序在需要证明时会有所帮助。 这是16英镑中的10英镑小额货币:
<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>
这是测试的背后代码:
private void Grid_SelectedItemChanged(object sender,RoutedPropertyChangedEventArgs<object> e)
{
    SelectedItemChanged(sender,e,\"Grid\");
}

private void TreeView_SelectedItemChanged(object sender,\"TreeView\");
    e.Handled = true;
}

private void TreeViewItem_SelectedItemChanged(object sender,\"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));
}
并运行它,然后单击第一项,将产生以下调试输出:
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
这表明事件是在
TreeView
本身上引发的,并且将
e.Handled
设置为
true
会阻止ѭ16receiving接收该事件。注释掉该行,它的确会膨胀到
Grid
。 但是在任何情况下,ѭ11都不会调用
SelectedItemChanged
处理程序。 当事情表现不正常时,请尝试使用小型测试程序。做实验并深入了解问题要容易得多!     ,阅读了里克的答案后,我与一位同事交谈,结果原来他曾经遇到过同样的问题。我在应用程序中尝试了各种操作(发现:TreeViewItem.Selected事件的行为与错误的行为完全相同)和一个测试项目,结果发现在测试应用程序中,这些事件的触发完全符合人们的预期。因此,环境之间必须存在显着差异(XAML和ViewModel类几乎相同),从而导致行为上的差异-罪魁祸首似乎是COM,正是在COM应用程序中精确地托管了WPF控件。 我的同事的应用程序是使用VSTO的Word扩展,而我的应用程序是Visual Studio 2010的VSPackage-而且Word和VS2010在大多数情况下仍是本机代码。另一方面,我的测试应用程序当然是一个小型的普通WPF项目。我向其中添加了一个带有ElementHost的WinForms表单,该表单又托管了一个带有TreeView的UserControl,但是仍然可以正常工作,所以对我来说,它看起来确实像宿主COM应用程序在某种程度上干扰了该事件。 TreeView和TreeViewItems。 幸运的是,我的同事发现/搜索了一个暂时可用的解决方案-在完成对事件的实际反应之后,在事件处理程序方法的结尾,再次将TreeViewItem设置为selected并将其聚焦:
item.Focus();
item.IsSelected = true;
我们不知道为什么,但是这将阻止错误地重新选择项目(从WPF角度看,这显然不是冒泡事件)。 再次感谢Rick推动我将TreeView和TreeViewItem事件分开的努力。     

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...