Skip to content

Commit

Permalink
feat: ExceptionReport
Browse files Browse the repository at this point in the history
  • Loading branch information
emako committed Sep 10, 2024
1 parent 02219f8 commit 715ad5d
Show file tree
Hide file tree
Showing 19 changed files with 673 additions and 4 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,28 @@ Similar to WPF UI.
<vio:ImageView Source="/wpfui.png" />
```

- ExceptionReport

> Show a dialog to handle the `DispatcherUnhandledException` from Application.
```c#
public partial class App : Application
{
public App()
{
InitializeComponent();

DispatcherUnhandledException += (object s, DispatcherUnhandledExceptionEventArgs e) =>
{
e.Handled = true;
ExceptionReport.Show(e.Exception);
};
}
}
```



### 📷 Screenshots

Under construction
Expand Down
11 changes: 10 additions & 1 deletion src/Wpf.Ui.Test/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Windows;
using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;
using Wpf.Ui.Violeta.Controls;

namespace Wpf.Ui.Test;
Expand All @@ -9,5 +11,12 @@ public App()
{
Splash.ShowAsync("pack://application:,,,/Wpf.Ui.Test;component/wpfui.png", 0.98d);
InitializeComponent();

DispatcherUnhandledException += (object s, DispatcherUnhandledExceptionEventArgs e) =>
{
Debug.WriteLine("Application.DispatcherUnhandledException " + e.Exception?.ToString() ?? string.Empty);
ExceptionReport.Show(e.Exception!);
e.Handled = true;
};
}
}
22 changes: 19 additions & 3 deletions src/Wpf.Ui.Test/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:vio="http://schemas.lepo.co/wpfui/2022/xaml/violeta"
Title="MainWindow"
Title="Wpf.Ui.Test"
Width="1200"
Height="800"
d:Background="#232323"
Expand All @@ -30,7 +30,7 @@
</ComboBox>
</ui:StackPanel>
</Grid>
<ScrollViewer Grid.Row="1">
<ScrollViewer x:Name="ScrollViewer" Grid.Row="1">
<StackPanel>
<TextBlock
FontSize="14"
Expand Down Expand Up @@ -635,7 +635,8 @@
<ui:TreeListView
Height="300"
Margin="0,8,90,0"
Model="{Binding TreeRegistryModel}">
Model="{Binding TreeRegistryModel}"
Visibility="Collapsed">
<ui:GridView>
<ui:GridView.Columns>
<ui:GridViewColumn Width="400" Header="Name">
Expand Down Expand Up @@ -722,6 +723,21 @@
<vio:ImageView Source="/wpfui.png" />
</ui:Border>
</StackPanel>
<StackPanel>
<TextBlock
MinWidth="120"
Margin="0,8,0,0"
FontSize="14"
FontWeight="Black"
Text="ExceptionReport" />
<ui:StackPanel
Margin="0,8,0,0"
Orientation="Horizontal"
Spacing="8">
<Button Command="{Binding ShowReportCommand}" Content="Show Report" />
<Button Command="{Binding ThrowExceptionCommand}" Content="Throw Exception" />
</ui:StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</ui:Grid>
Expand Down
24 changes: 24 additions & 0 deletions src/Wpf.Ui.Test/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public MainWindow()

Thread.Sleep(600);
Splash.CloseOnLoaded(this, minimumMilliseconds: 1800);

ScrollViewer.ScrollToEnd();
}

protected override void OnSourceInitialized(EventArgs e)
Expand Down Expand Up @@ -275,6 +277,28 @@ public static TreeCollection<TreeTestModel> CreateTestModel(int count1, int coun
}
return model;
}

[RelayCommand]
private void ShowReport()
{
ExceptionReport.Show(new SystemException(
"""
A critical system error occurred while attempting to perform the requested operation.
The system entered an unexpected state, possibly due to resource exhaustion,
incompatible configuration settings, or an internal logic flaw.
Immediate investigation is required to diagnose and rectify the issue.
Please check system logs, review recent changes,
and ensure that the environment meets all necessary requirements.
If the issue cannot be resolved, escalate to the technical team for further analysis.
"""
));
}

[RelayCommand]
private void ThrowException()
{
throw new InvalidOperationException("The operation could not be completed because the system encountered an unexpected state. This might be due to incorrect usage of the API or an internal error. Please ensure that all prerequisites are met and the operation is performed under the correct conditions. If the problem persists, consult the documentation or contact support for further assistance.");
}
}

public partial class RegistryModel : ITreeModel
Expand Down
41 changes: 41 additions & 0 deletions src/Wpf.Ui.Violeta/Controls/ExceptionReport/ExceptionReport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace Wpf.Ui.Violeta.Controls;

public static class ExceptionReport
{
public static void HandleOnUnhandledException(this Application app)
{
app.DispatcherUnhandledException -= OnApplicationUnhandledException;
app.DispatcherUnhandledException += OnApplicationUnhandledException;
}

private static void OnApplicationUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;

Debug.WriteLine("[ExceptionReport] Application.DispatcherUnhandledException " + e.Exception.ToString());
Show(e.Exception);
}

public static void Show(Exception e, string? appName = null, string? appVersion = null)
{
Window? owner = Application.Current.Windows.OfType<Window>().FirstOrDefault(window => window.IsActive)
?? Application.Current.MainWindow;

_ = Application.Current.Dispatcher.Invoke(() => _ = new ExceptionWindow(e, appName, appVersion) { Owner = owner }.ShowDialog());
}

public static async Task ShowAsync(Exception e, string? appName = null, string? appVersion = null)
{
Window? owner = Application.Current.Windows.OfType<Window>().FirstOrDefault(window => window.IsActive)
?? Application.Current.MainWindow;

await Application.Current.Dispatcher.BeginInvoke(() => _ = new ExceptionWindow(e, appName, appVersion) { Owner = owner }.ShowDialog());
}
}
149 changes: 149 additions & 0 deletions src/Wpf.Ui.Violeta/Controls/ExceptionReport/ExceptionWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<ui:FluentWindow
x:Class="Wpf.Ui.Violeta.Controls.ExceptionWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:vui="clr-namespace:Wpf.Ui.Controls"
Width="820"
Height="620"
MinWidth="820"
d:Background="#1A1A1A"
d:Foreground="White"
ExtendsContentIntoTitleBar="True"
FontSize="13"
WindowStartupLocation="CenterScreen"
WindowStyle="SingleBorderWindow"
mc:Ignorable="d">
<Window.Resources>
<FontFamily x:Key="SymbolThemeFontFamily">pack://application:,,,/Wpf.Ui.Violeta;component/Resources/Fonts/Segoe Fluent Icons.ttf#Segoe Fluent Icons</FontFamily>
</Window.Resources>
<Window.TaskbarItemInfo>
<TaskbarItemInfo ProgressState="Paused" ProgressValue="100" />
</Window.TaskbarItemInfo>
<Grid>
<Grid Margin="16,42,16,16">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ui:FontIcon
Grid.Column="0"
FontFamily="{DynamicResource SymbolThemeFontFamily}"
FontSize="28"
Glyph="{x:Static vui:FontSymbols.Warning}" />
<Grid
Grid.Column="1"
Margin="12,0,0,0"
VerticalAlignment="Center">
<StackPanel>
<TextBlock
x:Name="Hint1TextBlock"
VerticalAlignment="Center"
FontSize="20" />
<TextBlock
x:Name="Hint2TextBlock"
VerticalAlignment="Center"
FontSize="12" />
</StackPanel>
</Grid>
</Grid>
<Grid Grid.Row="1" Margin="0,12,0,0">
<StackPanel>
<TextBlock VerticalAlignment="Center">
<TextBlock.Inlines>
<Run Text="{Binding AppName}" />
<Run Text="{Binding AppVersion}" />
<Run Text="|" />
<Run Text="{Binding ErrorTime, Mode=OneTime}" />
<Run Text="|" />
<Run Text="{Binding OSVersion, Mode=OneTime}" />
</TextBlock.Inlines>
</TextBlock>
<TextBlock
Margin="0,12,0,0"
VerticalAlignment="Center"
FontWeight="Bold"
Foreground="#B83C4B"
Text="{Binding ExceptionType}" />
</StackPanel>
</Grid>
<Border
Grid.Row="2"
Margin="0,12,0,0"
Background="{DynamicResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{DynamicResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="3">
<ScrollViewer>
<StackPanel>
<TextBlock
Margin="12"
Foreground="#FFAC58"
Text="{Binding ExceptionObject.Message}"
TextWrapping="Wrap" />
<TextBlock
Margin="12"
Foreground="#FFAC58"
Text="{Binding ExceptionObject}"
TextWrapping="Wrap" />
</StackPanel>
</ScrollViewer>
</Border>
<Grid Grid.Row="3" Margin="0,12,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<vui:StackPanel
Grid.Column="0"
Orientation="Horizontal"
Spacing="10">
<ui:Button
x:Name="TryIgnoreButton"
MinWidth="120"
Appearance="{x:Static ui:ControlAppearance.Primary}">
<ui:Button.Content>
<vui:StackPanel Orientation="Horizontal" Spacing="6">
<ui:FontIcon FontFamily="{DynamicResource SymbolThemeFontFamily}" Glyph="{x:Static ui:FontSymbols.UpdateRestore}" />
<TextBlock x:Name="IgnoreTextBlock" />
</vui:StackPanel>
</ui:Button.Content>
</ui:Button>
<ui:Button x:Name="CopyButton" MinWidth="120">
<ui:Button.Content>
<vui:StackPanel Orientation="Horizontal" Spacing="6">
<ui:FontIcon FontFamily="{DynamicResource SymbolThemeFontFamily}" Glyph="{x:Static ui:FontSymbols.Copy}" />
<TextBlock x:Name="CopyTextBlock" />
</vui:StackPanel>
</ui:Button.Content>
</ui:Button>
</vui:StackPanel>
<vui:StackPanel
Grid.Column="1"
HorizontalAlignment="Right"
Orientation="Horizontal"
Spacing="10">
<ui:Button x:Name="ExitButton" MinWidth="120">
<ui:Button.Content>
<vui:StackPanel Orientation="Horizontal" Spacing="6">
<ui:FontIcon FontFamily="{DynamicResource SymbolThemeFontFamily}" Glyph="{x:Static ui:FontSymbols.Cancel}" />
<TextBlock x:Name="ExitTextBlock" />
</vui:StackPanel>
</ui:Button.Content>
</ui:Button>
</vui:StackPanel>
</Grid>
</Grid>
<ui:TitleBar Title="{Binding Title, RelativeSource={RelativeSource AncestorType=Window}}" />
</Grid>
</ui:FluentWindow>
Loading

0 comments on commit 715ad5d

Please sign in to comment.