Collapsed 事件在 TreeViewItem 的父节点上触发

Collapsed event fires on parent nodes of a TreeViewItem

我有一个这样定义的 WPF TreeView 控件:

<TreeView x:Name="samplesTree" MouseDoubleClick="samplesTree_MouseDoubleClick"
          KeyUp="samplesTree_KeyUp"
          SelectedItemChanged="samplesTree_SelectedItemChanged"
          IsVisibleChanged="treeView_IsVisibleChanged">
</TreeView>

我使用此代码跟踪展开或折叠了哪些节点:

private List<object> SamplesExpandedTags = new List<object>();

private void stag_Collapsed(object sender, RoutedEventArgs e)
{
    object tag = (sender as TreeViewItem).Tag;
    if (SamplesExpandedTags.Contains(tag))
        SamplesExpandedTags.Remove(tag);
}

private void stag_Expanded(object sender, RoutedEventArgs e)
{
    object tag = (sender as TreeViewItem).Tag;
    if (!SamplesExpandedTags.Contains(tag))
        SamplesExpandedTags.Add(tag);
}

...

// Items are created in code behind, not using binding to DataSource 
TreeViewItem item = new TreeViewItem();
item.Header = tv.NazevTypuVyrobku;
item.Tag = string.Format("TV{0}",tv.TypVyrobkuID);
item.Expanded += new RoutedEventHandler(stag_Expanded);
item.Collapsed += new RoutedEventHandler(stag_Collapsed);

通过调试我发现,当子节点被折叠时,父节点的 Collapsed 事件也会触发,所以 stag_Collapsed 对于整个父节点链来说是 运行实际折叠节点的元素。

我在stag_Collapsed方法的开头添加了这段代码:

if ((sender as TreeViewItem).IsExpanded) return;

现在代码可以正常工作了,但是为什么 Collapsed 事件会在所有父 TreeViewItem 上触发,而不仅仅是在实际折叠的 TreeViewItem 上触发?我希望发件人 IsExpanded 属性 总是 false


建议设置的解决方案:

e.Handled = true;

不是防弹的,因为这段代码:

subitem.Expanded += new RoutedEventHandler(stag_Expanded);
subitem.Expanded += new RoutedEventHandler(sampleOperation_Expanded);
subitem.Collapsed += new RoutedEventHandler(stag_Collapsed);

与此代码的工作方式不同:

subitem.Expanded += new RoutedEventHandler(sampleOperation_Expanded);
subitem.Expanded += new RoutedEventHandler(stag_Expanded);
subitem.Collapsed += new RoutedEventHandler(stag_Collapsed);

在第一种情况下,由于 e.Handled = true; 命令,sampleOperation_Expanded 根本没有执行。 我觉得that order of event handler execution应该不重要吧?

也许尝试在 stag_Collapsed() 方法中将 e.Handled 设置为 true。每 MSDN, "Marking the event handled will limit the visibility of the routed event to listeners along the event route".

private void stag_Collapsed(object sender, RoutedEventArgs e)
{
    object tag = (sender as TreeViewItem).Tag;
    if (SamplesExpandedTags.Contains(tag))
        SamplesExpandedTags.Remove(tag);
    e.Handled = true;
}