WPF:TreeViewItem Expanded / Collapsed事件捕获异常

时间:2018-04-08 03:00:33

标签: c# wpf xaml data-binding treeviewitem

我正在使用C#编写WPF应用程序,我遇到了一个有趣的问题。为什么忽略从TreeViewItem中的Expanded / Collapsed事件抛出的异常?其他事件(包括像MouseDoubleClick这样的TreeViewItem中的事件)表现出异常的正常行为。 Visual Studio中的诊断工具显示异常被抛出然后在PresentationFramework代码中捕获。例如,

XAML

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <TreeView>
            <TreeViewItem Header="Parent" Expanded="TreeViewItem_Expanded" MouseDoubleClick="TreeViewItem_MouseDoubleClick">
                <TreeViewItem Header="Child" />
            </TreeViewItem>
        </TreeView>
    </Grid>
</Window>

XAML.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
    {
        throw new Exception("Ignored"); //Same issue with Collapsed event
    }

    private void TreeViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        throw new Exception("Normal exception behavior");
    }
}

我正在努力实现一个延迟加载的TreeView,我花了大部分时间调试我的应用程序只是为了发现它是默默地失败并且原始问题是一个简单的修复。我使用Expanded和Collapsed事件的方法是完全错误的吗?如果没有,有没有优雅的方法可以让这些例外无声地失败?

1 个答案:

答案 0 :(得分:1)

此行为并非特定于Expanded事件或任何其他事件。

原因是您的异常被WPF绑定引擎“吞噬”了。 ControlTemplate的默认TreeViewItem包含ToggleButton,使用双向模式将IsChecked属性绑定到TreeViewItem.IsExpanded属性:

<ToggleButton IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"/>

所以整个过程看起来像:

  1. 您点击了项目的展开图标(实际上,这是ToggleButton)。
  2. ToggleButton将其IsChecked属性设置为true
  3. WPF绑定引擎将新值(true)传输到TreeViewItem的{​​{1}}属性。
  4. 树项展开并引发IsExpanded事件。
  5. 您在事件处理程序中抛出异常。
  6. 由于我们仍在处理绑定传输(步骤3),绑定引擎会捕获异常并将其记录到已配置的Expanded
  7. 工作流程继续,您在调用者的堆栈上看不到异常。
  8. WPF绑定引擎本机捕获异常,您无法更改它。 但是你可以实现自己的TraceListener,它可以抛出提供的异常,或者做一些其他的错误处理。

    查看this question及其答案。