TOC

This article has been localized into Polish by the community.

Aplikacja WPF:

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 dla Ciebie być niczym nowym. Za każdym razem, gdy masz kawałek kodu, który może rzucić wyjątkiem powinieneś otoczyć go w blok try-catch, aby poprawnie obsłużyć wyjątek. Dla przykładu rozważmy poniższy kawałek kodu:

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 rzucić wyjątkiem. 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 rzucony 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.Warning);
			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.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!