This article has been localized into Polish by the community.
Obsługa wyjątków w WPF
Jeśli znasz C#, lub jakikolwiek inny język .Net który może współpracować z WPF, to obsługa wyjątków nie powinna być niczym nowym dla Ciebie. Za każdym razem, gdy masz kawałek kodu, który może wygenerować wyjątek powinieneś otoczyć go w blok try-catch, aby poprawnie obsłużyć wyjątek. Dla przykładu rozważmy poniższy przykład.
private void Button_Click(object sender, RoutedEventArgs e)
{
string s = null;
s.Trim();
}
Oczywiście kod się nie wykona, ponieważ próbuję użyć metody Trim() na zmiennej, której wartość jest null. Jeśli nie obsłużysz wyjątku twoja aplikacja zostanie zamknięta i system Windows sam będzie musiał poradzić sobie z tym problem. Jak widzisz, nie jest to najlepszy sposób na przekazanie użytkownikowi, co poszło nie tak:
W takim przypadku użytkownik będzie zmuszony do zamknięcia aplikacji z powodu prostego i łatwego do ominięcia błędu. Jeśli wiesz, że coś może pójść nie tak, to powinieneś użyć bloku try-catch jak poniżej:
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);
}
}
Czasami jednak nawet najprostszy kod może wywołać wyjątek. Jednak, zamiast otaczać każda pojedynczą linijkę blokiem try-catch, można wykorzystać mechanizm WPF pozwalający na przechwycenie każdego nieobsłużonego wyjątku globalnie. Może osiągnąć to za pomocą zdarzenia DispatcherUnhandledException dostępnego w klasie Application. Funkcja obsługująca zdarzenie jest wywoływana wtedy, gdy wywołany wyjątek nie zostanie obsłużony w innej części kodu. Przykład powinien więc teraz wyglądać tak:
<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();
}
}
}
Zwróć uwagę, że wywołałem funkcję Trim() jeszcze raz poza blokiem try-catch. Tak więc pierwsze wywołanie będzie obsłużone, ale drugie już nie. Dla drugiego przypadku potrzebujemy trochę magii z pliku 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;
}
}
}
Zdarzenie globalne obsłużyliśmy tak samo jak lokalne zmieniając tylko odrobinę tekst i ilustrację informacji. Zauważ również, że ustawiłem właściwość e.Handled na true. Informuje to WPF, że zrobiliśmy już wszystko co trzeba z tym wyjątkiem i inne działania nie są już potrzebne.
Podsumowanie
Obsługa błędów jest bardzo ważną częścią każdej aplikacji. Całe szczęście WPF i .Net pozwala na łatwą obsługę wyjątków zarówno lokalnie jak i globalnie dla całej aplikacji. Jeśli tylko ma to sens powinieneś przechwytywać wyjątki lokalnie. Globalna obsługa wyjątków powinna być stosowana tylko w sytuacjach awaryjnych. Dlaczego? Lokalne chwytanie wyjątków pozwala na odpowiednie podejście do sytuacji i zareagowanie w odpowiedni sposób.