This article has been localized into Russian by the community.
Обработка исключений в WPF
Если Вы знакомы с C# или любым другим языком .NET, который можно использовать с WPF, то обработка исключений не вызовет у Вас больших затруднений: всякий раз, когда у Вас будет часть кода, которая с большой вероятностью может выдать исключение, Вам следует обернуть этот код в блок try-catch и изящно обработать исключение. Взгляните на следующий пример:
private void Button_Click(object sender, RoutedEventArgs e)
{
string s = null;
s.Trim();
}
Очевидно, что код в примере написан некорректно. Я пытаюсь исполнить метод Trim() на переменной, которая в текущий момент приняла значение null. Если не обработать исключение, в Вашем приложении произойдет сбой и Windows придется разбираться с данной проблемой. Как вы видите, это не выглядит чересчур уж "user friendly":
В данном случае, пользователь мог бы форсировать закрытие программы, из-за такой простой и легкообходимой ошибки. Так что, если Вы знаете, о том, что с кодом что-то может пойти не так - используйте блок try-catch таким образом:
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);
}
}
Однако, иногда даже простейший код может вызывать исключения, и, вместо того, чтобы оборачивать каждую строчку кода в блок try-catch, можно воспользоваться механизмом WPF, позволяющим глобально обрабатывать исключений. Это становится возможным с использованием события DispatcherUnhandledException в классе Application. Если Вы подписываетесь на это событие, WPF будет вызывать метод этой подписки каждый раз, когда будет появляться исключение, необработанное в Вашем коде. Вот полный пример, основанный на механизме, который мы только что обсудили:
<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>
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();
}
}
}
Обратите внимание, что я дополнительно использовал метод Trim() вне блока try-catch, и исключение появилось на первом вызове, а на втором - нет. Для второго нам необходимо немного магии App.xaml:
<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>
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.Error);
e.Handled = true;
}
}
}
В таком случае обработка исключения выглядит подобным образом как и для локальной обработки, с той лишь разницей, что сообщение об исключении содержит другой текст и изображение. Также, обратите внимание, что я определил свойство e.Handled как true. Это проинформирует WPF о том, что исключение уже обработано и с ним ничего не надо больше делать.
Итог
Обработка исключений - это очень важная часть любого приложения, и, к счастью, WPF и .NET делают этот процес легким, как для локальной, так и для глобальной обработки. Следует обрабатывать исключения локально, когда это необходимо, а глобальную обработку трактуйте как резервный механизм, поскольку локальная обработка позволит Вам управлять проблемой на более глубоком уровне.