Mitarbeitsnote-Aggregation (3.2)

Neuer Dialog berechnet aus den Sitzungs-Bewertungen je Schüler eine
Mitarbeitsnote (H1/H2/Gesamtjahr), mit editierbarer Aspekt-Gewichtung,
Trendanzeige und Übernahme als Grade (Category=Participation).
This commit is contained in:
2026-08-12 14:10:04 +02:00
parent 482942ce09
commit 182c386cc5
9 changed files with 392 additions and 7 deletions
@@ -0,0 +1,64 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
x:Class="LehrerApp.Desktop.Views.Groups.ParticipationGradeDialog"
x:DataType="vm:ParticipationGradeDialogViewModel"
Title="Mitarbeitsnote berechnen"
Width="620" Height="620" MinWidth="480" MinHeight="360"
CanResize="True" WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,Auto,*,Auto" Margin="24">
<TextBlock Grid.Row="0" Text="Mitarbeitsnote berechnen" FontSize="18" FontWeight="SemiBold"/>
<Grid Grid.Row="1" ColumnDefinitions="Auto,Auto,*" Margin="0,12,0,10">
<TextBlock Grid.Column="0" Text="Zeitraum:" VerticalAlignment="Center" Margin="0,0,8,0"/>
<ComboBox Grid.Column="1" ItemsSource="{Binding PeriodOptions}"
SelectedItem="{Binding SelectedPeriod}" MinWidth="180"/>
</Grid>
<StackPanel Grid.Row="2" Spacing="4" Margin="0,0,0,12">
<TextBlock Text="Gewichtung je Aspekt" FontSize="12" FontWeight="SemiBold" Opacity="0.6"/>
<ItemsControl ItemsSource="{Binding AspectWeights}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:AspectWeightItem">
<StackPanel Orientation="Horizontal" Spacing="6" Margin="0,0,16,4" VerticalAlignment="Center">
<TextBlock Text="{Binding Label}" VerticalAlignment="Center" FontSize="12"/>
<NumericUpDown Value="{Binding Weight}" Minimum="0" Maximum="10" Increment="0.1"
FormatString="0.#" Width="80" ShowButtonSpinner="False"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
<DataGrid Grid.Row="3"
ItemsSource="{Binding Rows}"
AutoGenerateColumns="False"
IsReadOnly="True"
GridLinesVisibility="Horizontal"
CanUserReorderColumns="False"
CanUserResizeColumns="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Schüler" Binding="{Binding Name}" Width="2*"/>
<DataGridTextColumn Header="Sitzungen" Binding="{Binding SessionCount}" Width="Auto"/>
<DataGridTextColumn Header="Ø Bewertung" Binding="{Binding AverageDisplay}" Width="Auto"/>
<DataGridTextColumn Header="Trend" Binding="{Binding TrendSymbol}" Width="Auto"/>
<DataGridTextColumn Header="Note" Binding="{Binding GradeDisplay}" Width="Auto"/>
</DataGrid.Columns>
</DataGrid>
<Grid Grid.Row="4" ColumnDefinitions="*,Auto,Auto" Margin="0,16,0,0">
<TextBlock Grid.Column="0" Text="{Binding StatusMessage}" Foreground="Green" FontSize="12"
VerticalAlignment="Center"
IsVisible="{Binding StatusMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
<Button Grid.Column="1" Content="Als Noten übernehmen" Command="{Binding ApplyCommand}" Margin="0,0,8,0"/>
<Button Grid.Column="2" Content="Schließen" Click="OnClose"/>
</Grid>
</Grid>
</Window>
@@ -0,0 +1,11 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace LehrerApp.Desktop.Views.Groups;
public partial class ParticipationGradeDialog : Window
{
public ParticipationGradeDialog() => InitializeComponent();
private void OnClose(object? sender, RoutedEventArgs e) => Close();
}
@@ -10,14 +10,17 @@
<Border Grid.Column="0"
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
BorderThickness="0,0,1,0">
<Grid RowDefinitions="Auto,*">
<Grid RowDefinitions="Auto,Auto,*">
<StackPanel Grid.Row="0" Orientation="Horizontal" Spacing="6" Margin="10,10,10,6">
<Button Content=" Sitzung" Command="{Binding AddSessionCommand}" HorizontalAlignment="Stretch"/>
<Button Content="Schnell" Command="{Binding QuickInputCommand}"/>
</StackPanel>
<ListBox Grid.Row="1"
<Button Grid.Row="1" Content="Ø Mitarbeitsnote" Command="{Binding ComputeGradeCommand}"
HorizontalAlignment="Stretch" Margin="10,0,10,6"/>
<ListBox Grid.Row="2"
ItemsSource="{Binding Sessions}"
SelectedItem="{Binding SelectedSession}"
BorderThickness="0">
@@ -1,7 +1,10 @@
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using LehrerApp.Core.Interfaces;
using LehrerApp.Core.Services;
using LehrerApp.Desktop.ViewModels.Groups;
using Microsoft.Extensions.DependencyInjection;
namespace LehrerApp.Desktop.Views.Groups;
@@ -20,6 +23,7 @@ public partial class ParticipationTabView : UserControl
_vm = vm;
vm.OnAddSession = ShowAddSessionDialog;
vm.OnQuickInput = ShowQuickInputDialog;
vm.OnComputeGrade = ShowComputeGradeDialog;
vm.Aspects.CollectionChanged += (_, _) => BuildColumns();
vm.PropertyChanged += (_, pe) =>
{
@@ -141,4 +145,22 @@ public partial class ParticipationTabView : UserControl
if (owner is not null)
await dialog.ShowDialog(owner);
}
private async Task ShowComputeGradeDialog(ParticipationTabViewModel tabVm)
{
var dialogVm = new ParticipationGradeDialogViewModel(
App.Services.GetRequiredService<IParticipationSessionRepository>(),
App.Services.GetRequiredService<IParticipationRepository>(),
App.Services.GetRequiredService<IParticipationAspectRepository>(),
App.Services.GetRequiredService<IStudentRepository>(),
App.Services.GetRequiredService<IEnrollmentRepository>(),
App.Services.GetRequiredService<IGradeRepository>(),
App.Services.GetRequiredService<GradingService>(),
tabVm.GroupId, tabVm.SchoolYear, tabVm.GradingSystem);
var dialog = new ParticipationGradeDialog { DataContext = dialogVm };
var owner = TopLevel.GetTopLevel(this) as Window;
if (owner is not null)
await dialog.ShowDialog(owner);
}
}