如果你熟悉C#或其他.NET语言,那么一定知道异常处理。任何时候,如果你觉得有段代码很有可能会抛出一个异常,那么就应该用try-catch块来处理这个异常。考虑下面的例子:
<span style="font-size:14px;">private void Button_Click(object sender, RoutedEventArgs e)
{
string s = null;
s.Trim();
}</span>
很明显,运行会出错,因为我试图把Trim()方法用到一个为null的变量上。如果你不处理这个异常,程序就会崩溃,系统不得不来处理这个问题,也就是弹出一个很不友好的界面:
用户不得不因为这个低级错误而关闭程序,然后这个错误是很好避免的。因此,只要你觉得哪里可能出问题,就用try-catch,如下:
<span style="font-size:14px;">private void Button_Click(object sender, RoutedEventArgs e)
{
string s = null;
try
{
s.Trim();
}
catch(Exception ex)
{
MessageBox.Show("A handled exception just occurred: " + ex.Message, "Exception Sample", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}</span>
然而,有时候最简单的代码都可能抛出异常,而我们不可能把每行代码都用try-catch括起来。WPF允许你处理全局范围内的异常,这是通过应用类里面的DispatcherUnhandledException事件来实现的。只要这个事件被订阅了,一旦异常被抛出而没有得到处理,WPF就会触发订阅的方法。下面是一个完整的代码,基于前面的例子:<span style="font-size:14px;"><Window x:Class="WpfTutorialSamples.WPF_Application.ExceptionHandlingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ExceptionHandlingSample" Height="200" Width="200">
<Grid>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click">
Do something bad!
</Button>
</Grid>
</Window></span>
<span style="font-size:14px;">using System;
using System.Windows;
namespace WpfTutorialSamples.WPF_Application
{
public partial class ExceptionHandlingSample : Window
{
public ExceptionHandlingSample()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
string s = null;
try
{
s.Trim();
}
catch(Exception ex)
{
MessageBox.Show("A handled exception just occurred: " + ex.Message, "Exception Sample", MessageBoxButton.OK, MessageBoxImage.Warning);
}
s.Trim();
}
}
}</span>
注意我在try-catch块外面又调用了一次Trim(),按理说,第一次的异常会被处理,第二次不会。现在我们在App.xaml里写下:
<span style="font-size:14px;"><Application x:Class="WpfTutorialSamples.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DispatcherUnhandledException="Application_DispatcherUnhandledException"
StartupUri="WPF Application/ExceptionHandlingSample.xaml">
<Application.Resources>
</Application.Resources>
</Application></span>
<span style="font-size:14px;">using System;
using System.Windows;
namespace WpfTutorialSamples
{
public partial class App : Application
{
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show("An unhandled exception just occurred: " + e.Exception.Message, "Exception Sample", MessageBoxButton.OK, MessageBoxImage.Warning);
e.Handled = true;
}
}
}</span>
处理的方法一样,唯一的区别是提示语和图标。同时注意到我把e.Handled设置为true了,它告诉WPF我们已经处理了这个异常,不在需要做别的了。
总结
异常处理是程序中非常重要的一个内容,所幸WPF和.NET让异常处理变得非常简单,不管是本地还是全局。在重要的地方处理本地异常,全局异常仅作为一个回调。因为本地处理异常,允许你更细致的解决问题。