WPF:TreeViewItem Expanded/Collapsed 事件捕获异常
WPF: TreeViewItem Expanded/Collapsed Event Catches Exceptions
我正在使用 C# 开发 WPF 应用程序,我遇到了一个有趣的问题。为什么忽略从 TreeViewItem 中的 Expanded/Collapsed 事件抛出的异常?其他事件,包括 TreeViewItem 中的那些事件,如 MouseDoubleClick,表现出异常的正常行为。 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 事件的方法是完全错误的吗?如果不是,是否有任何优雅的方法可以避免这些异常静默失败?
此行为并非特定于 Expanded
事件或任何其他事件。
原因是您的异常被 WPF 绑定引擎获取 "swallowed"。
TreeViewItem
的默认 ControlTemplate
包含一个 ToggleButton
,它使用 [=] 将其 IsChecked
属性 绑定到 TreeViewItem.IsExpanded
属性 55=]模式:
<ToggleButton IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"/>
所以整个过程是这样的:
- 您单击项目的展开图标(实际上,这是
ToggleButton
)。
-
ToggleButton
将其 IsChecked
属性 设置为 true
。
- WPF 绑定引擎将新值 (
true
) 传输到 TreeViewItem
的 IsExpanded
属性。
- 树项展开并引发
Expanded
事件。
- 您在事件处理程序中抛出异常。
- 由于我们仍在处理绑定传输(第 3 步),绑定引擎会捕获异常并将其记录到已配置的
TraceListener
.
- 工作流继续,您在调用者的堆栈上看不到异常。
WPF 绑定引擎本机捕获异常,您无法更改它。
但是您可以实现自己的 TraceListener
,它可以抛出所提供的异常或进行一些其他错误处理。
查看 this question 及其答案。
我正在使用 C# 开发 WPF 应用程序,我遇到了一个有趣的问题。为什么忽略从 TreeViewItem 中的 Expanded/Collapsed 事件抛出的异常?其他事件,包括 TreeViewItem 中的那些事件,如 MouseDoubleClick,表现出异常的正常行为。 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 事件的方法是完全错误的吗?如果不是,是否有任何优雅的方法可以避免这些异常静默失败?
此行为并非特定于 Expanded
事件或任何其他事件。
原因是您的异常被 WPF 绑定引擎获取 "swallowed"。
TreeViewItem
的默认 ControlTemplate
包含一个 ToggleButton
,它使用 [=] 将其 IsChecked
属性 绑定到 TreeViewItem.IsExpanded
属性 55=]模式:
<ToggleButton IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"/>
所以整个过程是这样的:
- 您单击项目的展开图标(实际上,这是
ToggleButton
)。 -
ToggleButton
将其IsChecked
属性 设置为true
。 - WPF 绑定引擎将新值 (
true
) 传输到TreeViewItem
的IsExpanded
属性。 - 树项展开并引发
Expanded
事件。 - 您在事件处理程序中抛出异常。
- 由于我们仍在处理绑定传输(第 3 步),绑定引擎会捕获异常并将其记录到已配置的
TraceListener
. - 工作流继续,您在调用者的堆栈上看不到异常。
WPF 绑定引擎本机捕获异常,您无法更改它。
但是您可以实现自己的 TraceListener
,它可以抛出所提供的异常或进行一些其他错误处理。
查看 this question 及其答案。