Fehlerbehandlung, Logging und feldbezogene Validierung (Kapitel 13.2)
Zentrale Exception-Behandlung (Dispatcher.UIThread.UnhandledException, AppDomain, TaskScheduler) verhindert Abstürze und protokolliert Fehler über AppLogger in eine rotierende Log-Datei im App-Datenverzeichnis. Toast-Benachrichtigungen zeigen Erfolg/Fehler global an. Alle Dialoge mit Formularfeldern zeigen Validierungsmeldungen jetzt direkt am betroffenen Feld statt in einem Sammel-Label. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="{Binding NameLabel}" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding Name}" PlaceholderText="{Binding NameHint}"/>
|
||||
<TextBlock Text="{Binding NameError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding NameError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Fach – AutoComplete aus bekannten Fächern; auch bei Klasse, da eine
|
||||
@@ -41,6 +43,8 @@
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Klassenstufe *" FontSize="12" Opacity="0.7"/>
|
||||
<NumericUpDown Value="{Binding GradeLevel}" Minimum="1" Maximum="13" FormatString="0"/>
|
||||
<TextBlock Text="{Binding GradeLevelError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding GradeLevelError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Schuljahr" FontSize="12" Opacity="0.7"/>
|
||||
@@ -70,8 +74,6 @@
|
||||
<CheckBox Content="Niveaudifferenzierung (E/G/Förder)" IsChecked="{Binding IsDifferentiated}"
|
||||
ToolTip.Tip="Blendet im Schüler-Tab eine Niveau-Zuordnung je Schüler ein und erlaubt in Klausuren die Zuordnung zu einem Niveau."/>
|
||||
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,8,*" Margin="0,20,0,0">
|
||||
|
||||
@@ -14,15 +14,14 @@
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Datum *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding DateText}" PlaceholderText="TT.MM.JJJJ" x:Name="DateBox"/>
|
||||
<TextBlock Text="{Binding DateTextError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding DateTextError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Kommentar (optional)" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding Comment}" PlaceholderText="z. B. Stunde 12 – Säure-Base-Reaktion"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,8,*" Margin="0,20,0,0">
|
||||
|
||||
@@ -15,14 +15,16 @@
|
||||
<Grid ColumnDefinitions="120,*,90" ColumnSpacing="6">
|
||||
<ComboBox Grid.Column="0" ItemsSource="{x:Static vm:GradeCategoryDisplay.Options}"
|
||||
SelectedItem="{Binding CategoryName}"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding DateText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<StackPanel Grid.Column="1" Spacing="2">
|
||||
<TextBox Text="{Binding DateText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<TextBlock Text="{Binding DateTextError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding DateTextError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<NumericUpDown Grid.Column="2" Value="{Binding Weight}" Minimum="0" Maximum="10"
|
||||
Increment="0.1" FormatString="0.#" ShowButtonSpinner="False"
|
||||
ToolTip.Tip="Gewichtung"/>
|
||||
</Grid>
|
||||
<TextBox Text="{Binding Note}" PlaceholderText="Notiz (z.B. Hausaufgabenkontrolle)"/>
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<TextBlock Text="Werte pro Schüler unten eintragen. Leere Felder werden nicht gespeichert."
|
||||
FontSize="11" Opacity="0.5" TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Titel *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding Title}" PlaceholderText="z.B. 1. Klausur Kinetik"/>
|
||||
<TextBlock Text="{Binding TitleError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding TitleError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="4" IsVisible="{Binding IsDifferentiated}">
|
||||
@@ -32,6 +34,8 @@
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Datum *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding DateText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<TextBlock Text="{Binding DateTextError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding DateTextError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Klausurnummer" FontSize="12" Opacity="0.7"/>
|
||||
@@ -41,6 +45,8 @@
|
||||
<StackPanel Grid.Column="4" Spacing="4">
|
||||
<TextBlock Text="Rückgabedatum" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding ReturnedAtText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<TextBlock Text="{Binding ReturnedAtTextError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding ReturnedAtTextError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -118,9 +124,6 @@
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
|
||||
<Separator Margin="0,4"/>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
|
||||
@@ -128,11 +128,17 @@
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock Text="Abschnitt abschließen" FontSize="12" FontWeight="SemiBold"/>
|
||||
<Grid ColumnDefinitions="*,100" ColumnSpacing="6">
|
||||
<TextBox Grid.Column="0" Text="{Binding NewSectionLabel}" PlaceholderText="Bezeichnung"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding NewSectionEndDateText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<StackPanel Grid.Column="0" Spacing="2">
|
||||
<TextBox Text="{Binding NewSectionLabel}" PlaceholderText="Bezeichnung"/>
|
||||
<TextBlock Text="{Binding NewSectionLabelError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding NewSectionLabelError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1" Spacing="2">
|
||||
<TextBox Text="{Binding NewSectionEndDateText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<TextBlock Text="{Binding NewSectionEndDateTextError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding NewSectionEndDateTextError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<TextBlock Text="{Binding SectionValidationMessage}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding SectionValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<Button Content="Abschnitt für alle Schüler abschließen" Command="{Binding CloseSectionCommand}"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
</StackPanel>
|
||||
|
||||
@@ -24,15 +24,21 @@
|
||||
<Grid ColumnDefinitions="120,*,90,90" ColumnSpacing="6">
|
||||
<ComboBox Grid.Column="0" ItemsSource="{x:Static vm:GradeCategoryDisplay.Options}"
|
||||
SelectedItem="{Binding CategoryName}"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding Value}" PlaceholderText="Wert (z.B. 2 oder 11)"/>
|
||||
<TextBox Grid.Column="2" Text="{Binding DateText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<StackPanel Grid.Column="1" Spacing="2">
|
||||
<TextBox Text="{Binding Value}" PlaceholderText="Wert (z.B. 2 oder 11)"/>
|
||||
<TextBlock Text="{Binding ValueError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding ValueError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="2">
|
||||
<TextBox Text="{Binding DateText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<TextBlock Text="{Binding DateTextError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding DateTextError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<NumericUpDown Grid.Column="3" Value="{Binding Weight}" Minimum="0" Maximum="10"
|
||||
Increment="0.1" FormatString="0.#" ShowButtonSpinner="False"
|
||||
ToolTip.Tip="Gewichtung"/>
|
||||
</Grid>
|
||||
<TextBox Text="{Binding Note}" PlaceholderText="Notiz (optional)" FontSize="12"/>
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<Grid ColumnDefinitions="*,Auto,Auto">
|
||||
<TextBlock Grid.Column="0" Text="{Binding CreatedAtDisplay}" FontSize="11" Opacity="0.5"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
xmlns:vs="clr-namespace:LehrerApp.Desktop.Views.Students"
|
||||
xmlns:vset="clr-namespace:LehrerApp.Desktop.Views.Settings"
|
||||
xmlns:vmset="clr-namespace:LehrerApp.Desktop.ViewModels.Settings"
|
||||
xmlns:svc="clr-namespace:LehrerApp.Desktop.Services"
|
||||
x:Class="LehrerApp.Desktop.Views.MainWindow"
|
||||
x:DataType="vm:MainWindowViewModel"
|
||||
Title="LehrerApp"
|
||||
Width="1280" Height="800"
|
||||
MinWidth="900" MinHeight="600">
|
||||
|
||||
<Panel>
|
||||
<!--
|
||||
Avalonia 12: DrawerPage ersetzt die selbstgebaute Sidebar.
|
||||
DrawerBreakpointWidth="900" → Sidebar ab 900px dauerhaft sichtbar,
|
||||
@@ -189,4 +191,32 @@
|
||||
</DrawerPage.Drawer>
|
||||
|
||||
</DrawerPage>
|
||||
|
||||
<!-- Toast-Benachrichtigungen (13.2.3): schweben über der aktuellen Seite, unten rechts. -->
|
||||
<ItemsControl ItemsSource="{Binding Toasts}"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
||||
Margin="0,0,20,20" IsHitTestVisible="False">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Spacing="8"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.Styles>
|
||||
<Style Selector="Border.toast">
|
||||
<Setter Property="Background" Value="#323232"/>
|
||||
</Style>
|
||||
<Style Selector="Border.toast.error">
|
||||
<Setter Property="Background" Value="#B3261E"/>
|
||||
</Style>
|
||||
</ItemsControl.Styles>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="svc:ToastItem">
|
||||
<Border Classes="toast" Classes.error="{Binding IsError}"
|
||||
CornerRadius="8" Padding="14,10" MaxWidth="360">
|
||||
<TextBlock Text="{Binding Message}" Foreground="White" FontSize="13" TextWrapping="Wrap"/>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Panel>
|
||||
</Window>
|
||||
|
||||
@@ -28,15 +28,20 @@
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Text="{Binding Validation}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding Validation, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
|
||||
<Grid ColumnDefinitions="*,8,90,8,Auto">
|
||||
<TextBox Grid.Column="0" Text="{Binding NewGrade}"
|
||||
PlaceholderText="Note (z.B. 2 oder 11)" FontSize="12"/>
|
||||
<NumericUpDown Grid.Column="2" Value="{Binding NewMinPercent}" Minimum="0" Maximum="100"
|
||||
FormatString="0.##" ShowButtonSpinner="False" FontSize="12"
|
||||
ToolTip.Tip="Mindest-Prozentgrenze"/>
|
||||
<StackPanel Grid.Column="0" Spacing="2">
|
||||
<TextBox Text="{Binding NewGrade}"
|
||||
PlaceholderText="Note (z.B. 2 oder 11)" FontSize="12"/>
|
||||
<TextBlock Text="{Binding NewGradeError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding NewGradeError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="2">
|
||||
<NumericUpDown Value="{Binding NewMinPercent}" Minimum="0" Maximum="100"
|
||||
FormatString="0.##" ShowButtonSpinner="False" FontSize="12"
|
||||
ToolTip.Tip="Mindest-Prozentgrenze"/>
|
||||
<TextBlock Text="{Binding NewMinPercentError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding NewMinPercentError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<Button Grid.Column="4" Content="+" Command="{Binding AddEntryCommand}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
@@ -47,8 +47,8 @@
|
||||
<Button Grid.Column="4" Content="Hinzufügen"
|
||||
Command="{Binding AddSubjectCommand}"/>
|
||||
</Grid>
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<TextBlock Text="{Binding NewNameError}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding NewNameError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
@@ -213,8 +213,8 @@
|
||||
<Button Grid.Column="4" Content="Anlegen"
|
||||
Command="{Binding AddGradingKeyTemplateCommand}"/>
|
||||
</Grid>
|
||||
<TextBlock Text="{Binding TemplateValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding TemplateValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<TextBlock Text="{Binding NewTemplateNameError}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding NewTemplateNameError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
|
||||
@@ -19,10 +19,14 @@
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Nachname *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding LastName}" PlaceholderText="Mustermann" x:Name="LastNameBox"/>
|
||||
<TextBlock Text="{Binding LastNameError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding LastNameError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Vorname *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding FirstName}" PlaceholderText="Max"/>
|
||||
<TextBlock Text="{Binding FirstNameError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding FirstNameError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -31,6 +35,8 @@
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Geburtsdatum" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding DateOfBirthText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<TextBlock Text="{Binding DateOfBirthError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding DateOfBirthError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Geschlecht" FontSize="12" Opacity="0.7"/>
|
||||
@@ -99,9 +105,6 @@
|
||||
AcceptsReturn="True" Height="70" TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Validierungsfehler -->
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Name *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox x:Name="NameBox" Text="{Binding Name}" PlaceholderText="Name"/>
|
||||
<TextBlock Text="{Binding NameError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding NameError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Beziehung" FontSize="12" Opacity="0.7"/>
|
||||
@@ -56,6 +58,8 @@
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Ungültig seit *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding InvalidSinceText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
<TextBlock Text="{Binding InvalidSinceError}" Foreground="Red" FontSize="11"
|
||||
IsVisible="{Binding InvalidSinceError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Grund" FontSize="12" Opacity="0.7"/>
|
||||
@@ -72,8 +76,6 @@
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user