diff --git a/README.md b/README.md index 5f90e72..c7d0225 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,17 @@ DependencyInjection and some Mvvm sugar | Package | Link | |-------------------------------------------------|-------------------------------------------------------------------------------| | RolandK.AvaloniaExtensions | https://www.nuget.org/packages/RolandK.AvaloniaExtensions | -| RolandK.AvaloniaExtensions.FluentThemeDetection | (obsolete due to Avalonia 11) | | RolandK.AvaloniaExtensions.DependencyInjection | https://www.nuget.org/packages/RolandK.AvaloniaExtensions.DependencyInjection | +| RolandK.AvaloniaExtensions.ExceptionHandling | https://www.nuget.org/packages/RolandK.AvaloniaExtensions.ExceptionHandling | +| RolandK.AvaloniaExtensions.FluentThemeDetection | (obsolete due to Avalonia 11) | ## Feature overview - [ViewServices over the popular Mvvm pattern by **not** providing an own Mvvm implementation](#viewservices-over-the-popular-mvvm-pattern) - [Some default ViewServices (FileDialogs, MessageBox)](#some-default-viewservices) - [Notification on ViewModels when view is attaching and detaching](#notification-on-viewmodels-when-view-is-attaching-and-detaching) - [DependencyInjection for Avalonia based on Microsft.Extensions.DependencyInjection](#dependencyinjection-for-avalonia-based-on-microsftextensionsdependencyinjection) + - [Error dialog for unhandled exceptions](#error-dialog-for-unhandled-exceptions) + - [Global error handling for unhandled exceptions](#global-error-handling-for-unhandled-exceptions) # Samples Here you find samples to the features of RolandK.AvaloniaExtensions. Most of @@ -257,4 +260,82 @@ in xaml namespace 'https://github.com/RolandK.AvaloniaExtensions' d:DataContext="{x:Static local:MainWindowViewModel.DesignViewModel}"> -``` \ No newline at end of file +``` + +## Error dialog for unhandled exceptions +Add nuget package [RolandK.AvaloniaExtensions.ErrorHandling](https://www.nuget.org/packages/RolandK.AvaloniaExtensions.ExceptionHandling) + +Then use a try-catch block like the following to show a dialog for unhandled exceptions. +```csharp + try + { + // Some logic + } + catch (Exception ex) + { + await GlobalErrorReporting.ShowGlobalExceptionDialogAsync(ex, this); + } +``` + +The method GlobalErrorReporting.ShowGlobalExceptionDialogAsync opens following modal dialog: +![Unhandled exception dialog](assets/screenshots/unhandled-exception-dialog.png) + +## Global error handling for unhandled exceptions +One draw back for Avalonia is that is does not offer something similar to +[Application.DispatcherUnhandledException](https://learn.microsoft.com/en-us/dotnet/api/system.windows.application.dispatcherunhandledexception) +in WPF. Therefore, you have little change to react anyhow on errors which you never expected +to happen. The only way you can handle these kind of exceptions is to wrap the entry point +of your application with a global try-catch. In order to show an error dialog in this case +I have the following solution. + +Add nuget package [RolandK.AvaloniaExtensions.ErrorHandling](https://www.nuget.org/packages/RolandK.AvaloniaExtensions.ExceptionHandling) + +Now modify the entry point of your application to handle exceptions like in the sample +application of this repository. +```csharp +[STAThread] +public static void Main(string[] args) +{ + try + { + BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + } + catch (Exception ex) + { + GlobalErrorReporting.TryShowBlockingGlobalExceptionDialogInAnotherProcess( + ex, + ".", + ".ExceptionViewer"); + } +} +``` + +So, what does GlobalErrorReporting.TryShowBlockingGlobalExceptionDialogInAnotherProcess do? +The problem here is, that we can't just show a dialog. We don't know in which state the +Avalonia application is currently. So, we need something to show the error dialog in a separate +process. GlobalErrorReporting.TryShowBlockingGlobalExceptionDialogInAnotherProcess does exactly this. +It collects error information, serializes it and sends it to a new instance of the +application '.ExceptionViewer'. So, just the application +'.ExceptionViewer' is now missing. + +In the next step, create a new Avalonia application in your solution that is called +'.ExceptionViewer'. There you also reference RolandK.AvaloniaExtensions.ErrorHandling. +Then you can remove MainWindow.axaml and modify App.xaml.cs to look like the following: + +```csharp +public partial class App : ExceptionViewerApplication +{ + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } +} +``` + +The base class ExceptionViewerApplication does the job then. It reads exception information +from incoming arguments and shows the error dialog. + +One last thing. You also need to add a reference from your application to '.ExceptionViewer'. +This ensures that the executable of our exception viewer is copied to the output directory +of your application. \ No newline at end of file diff --git a/assets/screenshots/unhandled-exception-dialog.png b/assets/screenshots/unhandled-exception-dialog.png new file mode 100644 index 0000000..d09adc4 Binary files /dev/null and b/assets/screenshots/unhandled-exception-dialog.png differ