Mitarbeit bewerten begonnen, Schülerdaten, Gruppen
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<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.AddSessionDialog"
|
||||
x:DataType="vm:AddSessionDialogViewModel"
|
||||
Title="Bewertungszeitpunkt anlegen"
|
||||
Width="380" SizeToContent="Height"
|
||||
CanResize="False" WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid RowDefinitions="*,Auto" Margin="24">
|
||||
<StackPanel Grid.Row="0" Spacing="14">
|
||||
<TextBlock Text="Neuer Bewertungszeitpunkt" FontSize="18" FontWeight="SemiBold"/>
|
||||
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Datum *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding DateText}" PlaceholderText="TT.MM.JJJJ" x:Name="DateBox"/>
|
||||
</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">
|
||||
<Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch" Click="OnCancel"/>
|
||||
<Button Grid.Column="2" Content="Anlegen" HorizontalAlignment="Stretch" Click="OnSave"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,27 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Groups;
|
||||
|
||||
public partial class AddSessionDialog : Window
|
||||
{
|
||||
public AddSessionDialog() => InitializeComponent();
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
this.FindControl<TextBox>("DateBox")?.Focus();
|
||||
}
|
||||
|
||||
private void OnSave(object? s, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is AddSessionDialogViewModel vm && vm.SaveCommand.CanExecute(null))
|
||||
{
|
||||
vm.SaveCommand.Execute(null);
|
||||
if (vm.Result is not null) Close(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCancel(object? s, RoutedEventArgs e) => Close(false);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<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.AddStudentToGroupDialog"
|
||||
x:DataType="vm:AddStudentToGroupDialogViewModel"
|
||||
Title="Schüler hinzufügen"
|
||||
Width="420" Height="500"
|
||||
CanResize="False" WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid RowDefinitions="Auto,*,Auto" Margin="24">
|
||||
|
||||
<!-- Überschrift + Suche -->
|
||||
<StackPanel Grid.Row="0" Spacing="12" Margin="0,0,0,12">
|
||||
<TextBlock Text="Schüler zur Gruppe hinzufügen" FontSize="18" FontWeight="SemiBold"/>
|
||||
<TextBox Text="{Binding SearchText}"
|
||||
PlaceholderText="Schüler suchen …"
|
||||
x:Name="SearchBox"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Schülerliste -->
|
||||
<ListBox Grid.Row="1"
|
||||
ItemsSource="{Binding AvailableStudents}"
|
||||
SelectedItem="{Binding SelectedStudent}"
|
||||
BorderThickness="1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:StudentPickerItem">
|
||||
<TextBlock Text="{Binding FullName}" Padding="4,2"/>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<!-- Validation + Buttons -->
|
||||
<StackPanel Grid.Row="2" Spacing="12" Margin="0,16,0,0">
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
<Grid ColumnDefinitions="*,8,*">
|
||||
<Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch" Click="OnCancel"/>
|
||||
<Button Grid.Column="2" Content="Hinzufügen" HorizontalAlignment="Stretch" Click="OnSave"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,27 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Groups;
|
||||
|
||||
public partial class AddStudentToGroupDialog : Window
|
||||
{
|
||||
public AddStudentToGroupDialog() => InitializeComponent();
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
this.FindControl<TextBox>("SearchBox")?.Focus();
|
||||
}
|
||||
|
||||
private void OnSave(object? s, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is AddStudentToGroupDialogViewModel vm && vm.SaveCommand.CanExecute(null))
|
||||
{
|
||||
vm.SaveCommand.Execute(null);
|
||||
if (vm.Result is not null) Close(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCancel(object? s, RoutedEventArgs e) => Close(false);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
|
||||
xmlns:views="clr-namespace:LehrerApp.Desktop.Views.Groups"
|
||||
x:Class="LehrerApp.Desktop.Views.Groups.GroupDetailView"
|
||||
x:DataType="vm:GroupDetailViewModel">
|
||||
|
||||
@@ -20,17 +21,14 @@
|
||||
<Run Text="{Binding StudentCount}"/>
|
||||
<Run Text=" Schüler"/>
|
||||
</TextBlock>
|
||||
<Button Content="+ Schüler" Command="{Binding AddStudentCommand}"/>
|
||||
<Button Content="+ Klausur" Command="{Binding AddExamCommand}"/>
|
||||
<Button Content="+ Schüler" Command="{Binding AddStudentCommand}"/>
|
||||
<Button Content="− Austragen" Command="{Binding RemoveStudentCommand}"
|
||||
IsVisible="{Binding SelectedStudent, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
||||
<Button Content="+ Klausur" Command="{Binding AddExamCommand}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!--
|
||||
Avalonia 12: TabbedPage ersetzt manuelles Tab-System.
|
||||
Kein ActiveTab-Property, kein IsVisible-Binding, keine eigenen Tab-Buttons.
|
||||
TabPlacement="Top" → Tabs oben (wie Browser-Tabs).
|
||||
-->
|
||||
<TabbedPage Grid.Row="1" TabPlacement="Top" SelectedIndex="{Binding ActiveTabIndex}">
|
||||
|
||||
<!-- Tab: Übersicht -->
|
||||
@@ -47,6 +45,7 @@
|
||||
<!-- Tab: Schüler -->
|
||||
<ContentPage Header="Schüler">
|
||||
<DataGrid ItemsSource="{Binding Students}"
|
||||
SelectedItem="{Binding SelectedStudent}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
@@ -61,6 +60,11 @@
|
||||
</DataGrid>
|
||||
</ContentPage>
|
||||
|
||||
<!-- Tab: Mitarbeit -->
|
||||
<ContentPage Header="Mitarbeit">
|
||||
<views:ParticipationTabView DataContext="{Binding ParticipationTab}"/>
|
||||
</ContentPage>
|
||||
|
||||
<!-- Tab: Klausuren -->
|
||||
<ContentPage Header="Klausuren">
|
||||
<DataGrid ItemsSource="{Binding Exams}"
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
using Avalonia.Controls;
|
||||
using LehrerApp.Core.Interfaces;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Groups;
|
||||
public partial class GroupDetailView : UserControl { public GroupDetailView() => InitializeComponent(); }
|
||||
|
||||
public partial class GroupDetailView : UserControl
|
||||
{
|
||||
public GroupDetailView() => InitializeComponent();
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is GroupDetailViewModel vm)
|
||||
vm.OnAddStudent = ShowAddStudentDialog;
|
||||
}
|
||||
|
||||
private async Task<bool> ShowAddStudentDialog()
|
||||
{
|
||||
if (DataContext is not GroupDetailViewModel vm || vm.Group is null) return false;
|
||||
|
||||
var dialogVm = new AddStudentToGroupDialogViewModel(
|
||||
App.Services.GetRequiredService<IStudentRepository>(),
|
||||
App.Services.GetRequiredService<IEnrollmentRepository>(),
|
||||
vm.Group.Id,
|
||||
vm.Group.SchoolYear);
|
||||
|
||||
var dialog = new AddStudentToGroupDialog { DataContext = dialogVm };
|
||||
var owner = TopLevel.GetTopLevel(this) as Window;
|
||||
if (owner is null) return false;
|
||||
|
||||
return await dialog.ShowDialog<bool>(owner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
<!-- Rechte Spalte: Platzhalter wenn keine Auswahl -->
|
||||
<StackPanel Grid.Column="1" HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" Spacing="8"
|
||||
IsVisible="{Binding !SelectedGroup}">
|
||||
IsVisible="{Binding SelectedGroup, Converter={x:Static ObjectConverters.IsNull}}">
|
||||
<TextBlock Text="Gruppe auswählen" FontSize="16" Opacity="0.4"
|
||||
HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="oder + Neue Gruppe anlegen" FontSize="12" Opacity="0.3"
|
||||
@@ -74,14 +74,15 @@
|
||||
</StackPanel>
|
||||
|
||||
<!-- Rechte Spalte: Gruppen-Übersicht wenn ausgewählt -->
|
||||
<ScrollViewer Grid.Column="1" IsVisible="{Binding SelectedGroup}">
|
||||
<ScrollViewer Grid.Column="1"
|
||||
IsVisible="{Binding SelectedGroup, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<StackPanel Margin="28,24" Spacing="20">
|
||||
|
||||
<!-- Gruppenname und Kurzinfos -->
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="{Binding SelectedGroup.DisplayName}"
|
||||
<TextBlock Text="{Binding SelectedGroupDisplayName}"
|
||||
FontSize="24" FontWeight="SemiBold" TextWrapping="Wrap"/>
|
||||
<TextBlock Text="{Binding SelectedGroup.Subtitle}"
|
||||
<TextBlock Text="{Binding SelectedGroupSubtitle}"
|
||||
FontSize="12" Opacity="0.55"/>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<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.ParticipationQuickInputDialog"
|
||||
x:DataType="vm:QuickInputViewModel"
|
||||
Title="Schnelleingabe Mitarbeit"
|
||||
Width="420" SizeToContent="Height"
|
||||
CanResize="False" WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid RowDefinitions="Auto,*,Auto" Margin="24">
|
||||
|
||||
<!-- Schülername + Fortschritt -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Margin="0,0,0,16">
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="{Binding StudentName}" FontSize="22" FontWeight="SemiBold"/>
|
||||
<TextBlock Text="{Binding CurrentAspectLabel}" FontSize="13" Opacity="0.5"/>
|
||||
</StackPanel>
|
||||
<TextBlock Grid.Column="1" Text="{Binding ProgressText}"
|
||||
VerticalAlignment="Top" FontSize="13" Opacity="0.4"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Aspektliste -->
|
||||
<ItemsControl Grid.Row="1" ItemsSource="{Binding AspectRows}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:QuickAspectRow">
|
||||
<Grid ColumnDefinitions="4,8,*,44" Margin="0,3">
|
||||
<!-- Aktiv-Balken links -->
|
||||
<Border Grid.Column="0" CornerRadius="2"
|
||||
Background="{DynamicResource SystemAccentColor}"
|
||||
IsVisible="{Binding IsActive}"/>
|
||||
<!-- Index-Badge -->
|
||||
<TextBlock Grid.Column="1" Text="{Binding Index, StringFormat='[{0}]'}"
|
||||
FontFamily="Monospace" FontSize="11" Opacity="0.4"
|
||||
VerticalAlignment="Center" Margin="0,0,6,0"/>
|
||||
<!-- Aspektname: bold wenn aktiv, gedimmt wenn nicht -->
|
||||
<TextBlock Grid.Column="2" Text="{Binding Label}" FontWeight="SemiBold"
|
||||
IsVisible="{Binding IsActive}" VerticalAlignment="Center"/>
|
||||
<TextBlock Grid.Column="2" Text="{Binding Label}" Opacity="0.55"
|
||||
IsVisible="{Binding IsActive, Converter={x:Static BoolConverters.Not}}"
|
||||
VerticalAlignment="Center"/>
|
||||
<!-- Aktueller Wert -->
|
||||
<TextBlock Grid.Column="3" Text="{Binding DisplayLabel}"
|
||||
FontFamily="Monospace" FontSize="16" FontWeight="Bold"
|
||||
TextAlignment="Right" VerticalAlignment="Center"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<!-- Tastenkürzel-Legende + Schließen-Button -->
|
||||
<StackPanel Grid.Row="2" Margin="0,16,0,0" Spacing="6">
|
||||
<TextBlock Opacity="0.35" FontSize="11" TextWrapping="Wrap"
|
||||
Text="1–5 bewerten · Q/W/E/R/T Aspekt wählen · Leertaste nächster Aspekt · Enter nächster Schüler · Backspace vorheriger · +/− anpassen · Esc schließen"/>
|
||||
<Button Content="Schließen" HorizontalAlignment="Stretch" Click="OnClose"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,54 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Groups;
|
||||
|
||||
public partial class ParticipationQuickInputDialog : Window
|
||||
{
|
||||
public ParticipationQuickInputDialog() => InitializeComponent();
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
Focus();
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is not QuickInputViewModel vm) { base.OnKeyDown(e); return; }
|
||||
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.D1 or Key.NumPad1: vm.SetRatingByNumber(1); e.Handled = true; break;
|
||||
case Key.D2 or Key.NumPad2: vm.SetRatingByNumber(2); e.Handled = true; break;
|
||||
case Key.D3 or Key.NumPad3: vm.SetRatingByNumber(3); e.Handled = true; break;
|
||||
case Key.D4 or Key.NumPad4: vm.SetRatingByNumber(4); e.Handled = true; break;
|
||||
case Key.D5 or Key.NumPad5: vm.SetRatingByNumber(5); e.Handled = true; break;
|
||||
|
||||
case Key.Q: vm.SelectAspect(0); e.Handled = true; break;
|
||||
case Key.W: vm.SelectAspect(1); e.Handled = true; break;
|
||||
case Key.E: vm.SelectAspect(2); e.Handled = true; break;
|
||||
case Key.R: vm.SelectAspect(3); e.Handled = true; break;
|
||||
case Key.T: vm.SelectAspect(4); e.Handled = true; break;
|
||||
|
||||
case Key.Space: vm.NextAspect(); e.Handled = true; break;
|
||||
case Key.Enter:
|
||||
if (vm.IsLastStudent) Close();
|
||||
else vm.NextStudent();
|
||||
e.Handled = true;
|
||||
break;
|
||||
case Key.Back: vm.PreviousStudent(); e.Handled = true; break;
|
||||
|
||||
case Key.OemPlus or Key.Add: vm.IncrementRating(); e.Handled = true; break;
|
||||
case Key.OemMinus or Key.Subtract: vm.DecrementRating(); e.Handled = true; break;
|
||||
|
||||
case Key.Escape: Close(); e.Handled = true; break;
|
||||
|
||||
default: base.OnKeyDown(e); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClose(object? s, RoutedEventArgs e) => Close();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<UserControl 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.ParticipationTabView"
|
||||
x:DataType="vm:ParticipationTabViewModel">
|
||||
|
||||
<Grid ColumnDefinitions="220,*">
|
||||
|
||||
<!-- Linke Seite: Sitzungsliste -->
|
||||
<Border Grid.Column="0"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,0,1,0">
|
||||
<Grid RowDefinitions="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"
|
||||
ItemsSource="{Binding Sessions}"
|
||||
SelectedItem="{Binding SelectedSession}"
|
||||
BorderThickness="0">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:ParticipationSessionItem">
|
||||
<TextBlock Text="{Binding Display}" TextWrapping="Wrap" Padding="4,3" FontSize="12"/>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Rechte Seite: Bewertungsraster (wird per Code-Behind aufgebaut) -->
|
||||
<Grid Grid.Column="1" RowDefinitions="Auto,*">
|
||||
<TextBlock Grid.Row="0"
|
||||
Text="{Binding SelectedSessionDisplay}"
|
||||
FontSize="13" FontWeight="SemiBold" Margin="12,10,12,4"
|
||||
IsVisible="{Binding SelectedSession, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
||||
|
||||
<!-- DataGrid: Spalten werden in ParticipationTabView.axaml.cs dynamisch erzeugt -->
|
||||
<DataGrid Grid.Row="1"
|
||||
x:Name="RatingGrid"
|
||||
ItemsSource="{Binding StudentRows}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="All"
|
||||
CanUserReorderColumns="False"
|
||||
CanUserResizeColumns="True"
|
||||
IsVisible="{Binding SelectedSession, Converter={x:Static ObjectConverters.IsNotNull}}"/>
|
||||
|
||||
<TextBlock Grid.Row="1"
|
||||
Text="{Binding NoDataText}"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
Opacity="0.35" FontSize="14"
|
||||
IsVisible="{Binding SelectedSession, Converter={x:Static ObjectConverters.IsNull}}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,121 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using LehrerApp.Desktop.ViewModels.Groups;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Groups;
|
||||
|
||||
public partial class ParticipationTabView : UserControl
|
||||
{
|
||||
private ParticipationTabViewModel? _vm;
|
||||
|
||||
public ParticipationTabView() => InitializeComponent();
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
|
||||
if (DataContext is ParticipationTabViewModel vm)
|
||||
{
|
||||
_vm = vm;
|
||||
vm.OnAddSession = ShowAddSessionDialog;
|
||||
vm.OnQuickInput = ShowQuickInputDialog;
|
||||
vm.Aspects.CollectionChanged += (_, _) => BuildColumns();
|
||||
BuildColumns();
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildColumns()
|
||||
{
|
||||
var grid = this.FindControl<DataGrid>("RatingGrid");
|
||||
if (grid is null || _vm is null) return;
|
||||
|
||||
grid.Columns.Clear();
|
||||
|
||||
grid.Columns.Add(new DataGridTextColumn
|
||||
{
|
||||
Header = "Schüler",
|
||||
Binding = new Binding("Name"),
|
||||
Width = new DataGridLength(160, DataGridLengthUnitType.Pixel),
|
||||
});
|
||||
|
||||
foreach (var (aspect, i) in _vm.Aspects.Select((a, i) => (a, i)))
|
||||
{
|
||||
var capturedIndex = i;
|
||||
grid.Columns.Add(new DataGridTemplateColumn
|
||||
{
|
||||
Header = $"{aspect.Label} [{AspectShortcut(i)}]",
|
||||
Width = new DataGridLength(1, DataGridLengthUnitType.Star),
|
||||
CellTemplate = BuildCellTemplate(capturedIndex),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static IDataTemplate BuildCellTemplate(int aspectIndex)
|
||||
{
|
||||
return new FuncDataTemplate<ParticipationStudentRow>((row, _) =>
|
||||
{
|
||||
if (row is null) return new TextBlock();
|
||||
|
||||
var cell = row.Cells.ElementAtOrDefault(aspectIndex);
|
||||
if (cell is null) return new TextBlock();
|
||||
|
||||
var panel = new StackPanel
|
||||
{
|
||||
Orientation = Avalonia.Layout.Orientation.Horizontal,
|
||||
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
|
||||
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
|
||||
Spacing = 2,
|
||||
Margin = new Avalonia.Thickness(0, 2),
|
||||
};
|
||||
|
||||
foreach (var (label, val) in new[] { ("−−", -2), ("−", -1), ("∼", 0), ("+", 1), ("++", 2) })
|
||||
{
|
||||
var btn = new Button
|
||||
{
|
||||
Content = label,
|
||||
Padding = new Avalonia.Thickness(5, 1),
|
||||
FontSize = 11,
|
||||
Opacity = cell.Value == val ? 1.0 : 0.3,
|
||||
};
|
||||
var capturedVal = val;
|
||||
btn.Click += (_, _) => cell.SetValue(capturedVal);
|
||||
cell.PropertyChanged += (_, pe) =>
|
||||
{
|
||||
if (pe.PropertyName == nameof(RatingCell.Value))
|
||||
btn.Opacity = cell.Value == capturedVal ? 1.0 : 0.3;
|
||||
};
|
||||
panel.Children.Add(btn);
|
||||
}
|
||||
|
||||
return panel;
|
||||
});
|
||||
}
|
||||
|
||||
private static string AspectShortcut(int i) => i switch
|
||||
{
|
||||
0 => "Q", 1 => "W", 2 => "E", 3 => "R", 4 => "T", _ => ""
|
||||
};
|
||||
|
||||
private async Task<LehrerApp.Core.Models.ParticipationSession?> ShowAddSessionDialog()
|
||||
{
|
||||
var vm = new AddSessionDialogViewModel();
|
||||
var dialog = new AddSessionDialog { DataContext = vm };
|
||||
var owner = TopLevel.GetTopLevel(this) as Window;
|
||||
if (owner is null) return null;
|
||||
var ok = await dialog.ShowDialog<bool>(owner);
|
||||
return ok ? vm.Result : null;
|
||||
}
|
||||
|
||||
private async Task ShowQuickInputDialog(ParticipationTabViewModel tabVm)
|
||||
{
|
||||
if (tabVm.StudentRows.Count == 0) return;
|
||||
var quickVm = new QuickInputViewModel(
|
||||
tabVm.StudentRows.ToList(),
|
||||
tabVm.Aspects.ToList());
|
||||
var dialog = new ParticipationQuickInputDialog { DataContext = quickVm };
|
||||
var owner = TopLevel.GetTopLevel(this) as Window;
|
||||
if (owner is not null)
|
||||
await dialog.ShowDialog(owner);
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@
|
||||
<Border DockPanel.Dock="Bottom" Padding="12,8"
|
||||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
BorderThickness="0,1,0,0">
|
||||
<views:SyncStatusBar/>
|
||||
<views:SyncStatusBar DataContext="{Binding SyncStatus}"/>
|
||||
</Border>
|
||||
|
||||
<ScrollViewer>
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Students"
|
||||
x:Class="LehrerApp.Desktop.Views.Students.AddStudentDialog"
|
||||
x:DataType="vm:AddStudentDialogViewModel"
|
||||
Title="Neuer Schüler"
|
||||
Width="500" Height="640"
|
||||
CanResize="True" WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid RowDefinitions="*,Auto" Margin="24,20,24,20">
|
||||
|
||||
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Spacing="14">
|
||||
|
||||
<TextBlock Text="Neuen Schüler anlegen" FontSize="18" FontWeight="SemiBold"/>
|
||||
|
||||
<!-- Name -->
|
||||
<Grid ColumnDefinitions="*,10,*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Nachname *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding LastName}" PlaceholderText="Mustermann" x:Name="LastNameBox"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Vorname *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding FirstName}" PlaceholderText="Max"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Geburtsdatum + Geschlecht -->
|
||||
<Grid ColumnDefinitions="*,10,*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Geburtsdatum" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding DateOfBirthText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Geschlecht" FontSize="12" Opacity="0.7"/>
|
||||
<ComboBox ItemsSource="{Binding GenderOptions}"
|
||||
SelectedItem="{Binding SelectedGender}"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Kontakte -->
|
||||
<StackPanel Spacing="6">
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBlock Grid.Column="0" Text="Kontakte" FontSize="14" FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"/>
|
||||
<Button Grid.Column="1" Content="+ Kontakt" Command="{Binding AddContactCommand}"
|
||||
FontSize="12" Padding="8,4"/>
|
||||
</Grid>
|
||||
|
||||
<ItemsControl ItemsSource="{Binding Contacts}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:ContactEntryViewModel">
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="6" Padding="10,8" Margin="0,0,0,6">
|
||||
<StackPanel Spacing="6">
|
||||
<!-- Zeile 1: Name + Beziehung + Löschen -->
|
||||
<Grid ColumnDefinitions="*,10,*,10,Auto">
|
||||
<TextBox Grid.Column="0" Text="{Binding Name}"
|
||||
PlaceholderText="Name" FontSize="12"/>
|
||||
<ComboBox Grid.Column="2"
|
||||
ItemsSource="{Binding $parent[Window].DataContext.RelationPresets}"
|
||||
SelectedItem="{Binding Relation}"
|
||||
HorizontalAlignment="Stretch" FontSize="12"/>
|
||||
<Button Grid.Column="4" Content="×" Padding="6,2"
|
||||
Command="{Binding RemoveCommand}" FontSize="14"/>
|
||||
</Grid>
|
||||
<!-- Zeile 2: Telefon + E-Mail -->
|
||||
<Grid ColumnDefinitions="*,10,*">
|
||||
<TextBox Grid.Column="0" Text="{Binding Phone}"
|
||||
PlaceholderText="Telefon / Handy" FontSize="12"/>
|
||||
<TextBox Grid.Column="2" Text="{Binding Email}"
|
||||
PlaceholderText="E-Mail" FontSize="12"/>
|
||||
</Grid>
|
||||
<!-- Zeile 3: Adresse -->
|
||||
<TextBox Text="{Binding Street}" PlaceholderText="Straße und Hausnummer" FontSize="12"/>
|
||||
<Grid ColumnDefinitions="100,10,*">
|
||||
<TextBox Grid.Column="0" Text="{Binding PostalCode}"
|
||||
PlaceholderText="PLZ" FontSize="12"/>
|
||||
<TextBox Grid.Column="2" Text="{Binding City}"
|
||||
PlaceholderText="Ort" FontSize="12"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Text="Noch keine Kontakte. Über + Kontakt hinzufügen."
|
||||
Opacity="0.35" FontSize="12"
|
||||
IsVisible="{Binding !Contacts.Count}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Notizen -->
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Notizen" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding Notes}" PlaceholderText="Interne Anmerkungen …"
|
||||
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>
|
||||
|
||||
<!-- Buttons -->
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,10,*" Margin="0,16,0,0">
|
||||
<Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch" Click="OnCancel"/>
|
||||
<Button Grid.Column="2" Content="Anlegen" HorizontalAlignment="Stretch" Click="OnSave"/>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,27 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using LehrerApp.Desktop.ViewModels.Students;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Students;
|
||||
|
||||
public partial class AddStudentDialog : Window
|
||||
{
|
||||
public AddStudentDialog() => InitializeComponent();
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
this.FindControl<TextBox>("LastNameBox")?.Focus();
|
||||
}
|
||||
|
||||
private void OnSave(object? s, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is AddStudentDialogViewModel vm && vm.SaveCommand.CanExecute(null))
|
||||
{
|
||||
vm.SaveCommand.Execute(null);
|
||||
if (vm.Result is not null) Close(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCancel(object? s, RoutedEventArgs e) => Close(false);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Students"
|
||||
x:Class="LehrerApp.Desktop.Views.Students.AddressViewerWindow"
|
||||
x:DataType="vm:ContactItem"
|
||||
Title="Adresse"
|
||||
Width="340" Height="230"
|
||||
MinWidth="280" MinHeight="180"
|
||||
CanResize="True"
|
||||
ShowInTaskbar="False"
|
||||
WindowStartupLocation="Manual">
|
||||
|
||||
<Grid RowDefinitions="Auto,*,Auto" Margin="18">
|
||||
<StackPanel Grid.Row="0" Spacing="3">
|
||||
<TextBlock Text="{Binding Name}" FontSize="16" FontWeight="SemiBold"/>
|
||||
<TextBlock Text="{Binding Relation}" FontSize="12" Opacity="0.55"/>
|
||||
</StackPanel>
|
||||
|
||||
<Border Grid.Row="1" Margin="0,14" Padding="12"
|
||||
Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="7">
|
||||
<TextBox Text="{Binding Address}" IsReadOnly="True"
|
||||
AcceptsReturn="True" TextWrapping="Wrap"
|
||||
BorderThickness="0" Background="Transparent"
|
||||
VerticalContentAlignment="Center"/>
|
||||
</Border>
|
||||
|
||||
<TextBlock Grid.Row="2"
|
||||
Text="Das Fenster kann verschoben und parallel weiter geöffnet bleiben."
|
||||
FontSize="10" Opacity="0.45" TextWrapping="Wrap"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,18 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Students;
|
||||
|
||||
public partial class AddressViewerWindow : Window
|
||||
{
|
||||
public AddressViewerWindow() => InitializeComponent();
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
if (Owner is not Window owner) return;
|
||||
Position = new PixelPoint(
|
||||
owner.Position.X + Math.Max(20, (int)owner.Bounds.Width - (int)Width - 24),
|
||||
owner.Position.Y + Math.Max(20, (int)owner.Bounds.Height - (int)Height - 48));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Students"
|
||||
x:Class="LehrerApp.Desktop.Views.Students.ContactEditDialog"
|
||||
x:DataType="vm:ContactEditDialogViewModel"
|
||||
Title="{Binding DialogTitle}"
|
||||
Width="520" Height="650"
|
||||
MinWidth="460" MinHeight="560"
|
||||
CanResize="True" WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid RowDefinitions="*,Auto" Margin="24,20">
|
||||
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Spacing="16">
|
||||
<TextBlock Text="{Binding DialogTitle}" FontSize="18" FontWeight="SemiBold"/>
|
||||
|
||||
<Grid ColumnDefinitions="*,10,*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Name *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox x:Name="NameBox" Text="{Binding Name}" PlaceholderText="Name"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Beziehung" FontSize="12" Opacity="0.7"/>
|
||||
<ComboBox ItemsSource="{Binding RelationPresets}"
|
||||
SelectedItem="{Binding Relation}"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Grid ColumnDefinitions="*,10,*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Telefon" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding Phone}" PlaceholderText="Telefon / Handy"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="E-Mail" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding Email}" PlaceholderText="E-Mail"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="Adresse" FontSize="14" FontWeight="SemiBold"/>
|
||||
<TextBox Text="{Binding Street}" PlaceholderText="Straße und Hausnummer"/>
|
||||
<Grid ColumnDefinitions="110,10,*">
|
||||
<TextBox Grid.Column="0" Text="{Binding PostalCode}" PlaceholderText="PLZ"/>
|
||||
<TextBox Grid.Column="2" Text="{Binding City}" PlaceholderText="Ort"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<Separator/>
|
||||
|
||||
<CheckBox Content="Dieser Kontakt gilt nicht mehr"
|
||||
IsChecked="{Binding IsInvalid}"/>
|
||||
|
||||
<StackPanel Spacing="10" IsVisible="{Binding IsInvalid}">
|
||||
<Grid ColumnDefinitions="*,10,*">
|
||||
<StackPanel Grid.Column="0" Spacing="4">
|
||||
<TextBlock Text="Ungültig seit *" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding InvalidSinceText}" PlaceholderText="TT.MM.JJJJ"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Spacing="4">
|
||||
<TextBlock Text="Grund" FontSize="12" Opacity="0.7"/>
|
||||
<ComboBox ItemsSource="{Binding InvalidReasonOptions}"
|
||||
SelectedItem="{Binding SelectedInvalidReason}"
|
||||
HorizontalAlignment="Stretch"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Ergänzung zum Grund" FontSize="12" Opacity="0.7"/>
|
||||
<TextBox Text="{Binding InvalidReasonDetails}"
|
||||
PlaceholderText="Optionaler Hinweis"
|
||||
AcceptsReturn="True" Height="60" TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Text="{Binding ValidationMessage}" Foreground="Red" FontSize="12"
|
||||
IsVisible="{Binding ValidationMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,10,*" Margin="0,18,0,0">
|
||||
<Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch"
|
||||
Click="OnCancel"/>
|
||||
<Button Grid.Column="2" Content="Speichern" HorizontalAlignment="Stretch"
|
||||
Click="OnSave"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,25 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using LehrerApp.Desktop.ViewModels.Students;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Students;
|
||||
|
||||
public partial class ContactEditDialog : Window
|
||||
{
|
||||
public ContactEditDialog() => InitializeComponent();
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
this.FindControl<TextBox>("NameBox")?.Focus();
|
||||
}
|
||||
|
||||
private void OnSave(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not ContactEditDialogViewModel vm) return;
|
||||
vm.SaveCommand.Execute(null);
|
||||
if (vm.Result is not null) Close(true);
|
||||
}
|
||||
|
||||
private void OnCancel(object? sender, RoutedEventArgs e) => Close(false);
|
||||
}
|
||||
@@ -60,6 +60,74 @@
|
||||
</ScrollViewer>
|
||||
</ContentPage>
|
||||
|
||||
<ContentPage Header="Kontakte">
|
||||
<Grid RowDefinitions="Auto,*" Margin="20">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto,Auto" Margin="0,0,0,10">
|
||||
<TextBlock Grid.Column="0" Text="Kontaktdaten" FontSize="15"
|
||||
FontWeight="SemiBold" VerticalAlignment="Center"/>
|
||||
<Button Grid.Column="1" Content="+ Neu" Command="{Binding AddContactCommand}"
|
||||
Margin="0,0,8,0"/>
|
||||
<Button Grid.Column="2" Content="Bearbeiten" Command="{Binding EditContactCommand}"
|
||||
Margin="0,0,8,0"/>
|
||||
<Button Grid.Column="3" Content="Adresse anzeigen"
|
||||
Command="{Binding ViewSelectedAddressCommand}"/>
|
||||
</Grid>
|
||||
|
||||
<ListBox Grid.Row="1" x:Name="ContactList"
|
||||
ItemsSource="{Binding Contacts}"
|
||||
SelectedItem="{Binding SelectedContact}"
|
||||
DoubleTapped="OnContactDoubleTapped">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:ContactItem">
|
||||
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||||
CornerRadius="8" Padding="14,10" Margin="2,3">
|
||||
<Grid ColumnDefinitions="220,*,Auto" RowDefinitions="Auto,Auto">
|
||||
<StackPanel Grid.Column="0" Grid.RowSpan="2" Spacing="4">
|
||||
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" FontSize="14"
|
||||
TextWrapping="Wrap"/>
|
||||
<Border Background="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||||
CornerRadius="4" Padding="6,2" HorizontalAlignment="Left">
|
||||
<TextBlock Text="{Binding Relation}" FontSize="11" Opacity="0.7"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal" Spacing="8">
|
||||
<Button Content="{Binding PhoneDisplay}"
|
||||
Command="{Binding CallCommand}"
|
||||
IsVisible="{Binding HasPhone}"
|
||||
FontSize="12" Padding="8,4"/>
|
||||
<Button Content="{Binding EmailDisplay}"
|
||||
Command="{Binding MailCommand}"
|
||||
IsVisible="{Binding HasEmail}"
|
||||
FontSize="12" Padding="8,4"/>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding Address}"
|
||||
IsVisible="{Binding HasAddress}" FontSize="12" Opacity="0.65"
|
||||
TextWrapping="Wrap" Margin="4,4,12,0"/>
|
||||
|
||||
<Border Grid.Column="2" Grid.RowSpan="2" CornerRadius="4" Padding="7,3"
|
||||
VerticalAlignment="Top"
|
||||
Background="{DynamicResource SystemControlBackgroundAltHighBrush}">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding StatusText}" FontSize="11"
|
||||
IsVisible="{Binding IsInvalid}" Foreground="IndianRed"/>
|
||||
<TextBlock Text="Aktuell" FontSize="11" Opacity="0.5"
|
||||
IsVisible="{Binding IsValid}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<TextBlock Text="Keine Kontakte erfasst." Opacity="0.4"
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||
IsVisible="{Binding HasNoContacts}"/>
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
|
||||
<ContentPage Header="Noten">
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBlock Text="Notenübersicht" FontSize="16" Opacity="0.4" HorizontalAlignment="Center"/>
|
||||
|
||||
@@ -1,3 +1,48 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using LehrerApp.Core.Models;
|
||||
using LehrerApp.Desktop.ViewModels.Students;
|
||||
|
||||
namespace LehrerApp.Desktop.Views.Students;
|
||||
public partial class StudentDetailView : UserControl { public StudentDetailView() => InitializeComponent(); }
|
||||
|
||||
public partial class StudentDetailView : UserControl
|
||||
{
|
||||
public StudentDetailView() => InitializeComponent();
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
if (DataContext is not StudentDetailViewModel vm) return;
|
||||
vm.OnEditContact = ShowContactDialog;
|
||||
vm.OnViewAddress = ShowAddressViewer;
|
||||
}
|
||||
|
||||
private async Task<Contact?> ShowContactDialog(Contact? contact)
|
||||
{
|
||||
var owner = TopLevel.GetTopLevel(this) as Window;
|
||||
if (owner is null) return null;
|
||||
|
||||
var vm = new ContactEditDialogViewModel(contact);
|
||||
var dialog = new ContactEditDialog { DataContext = vm };
|
||||
var saved = await dialog.ShowDialog<bool>(owner);
|
||||
return saved ? vm.Result : null;
|
||||
}
|
||||
|
||||
private void ShowAddressViewer(ContactItem contact)
|
||||
{
|
||||
if (!contact.HasAddress) return;
|
||||
var owner = TopLevel.GetTopLevel(this) as Window;
|
||||
var viewer = new AddressViewerWindow { DataContext = contact };
|
||||
if (owner is not null)
|
||||
viewer.Show(owner);
|
||||
else
|
||||
viewer.Show();
|
||||
}
|
||||
|
||||
private void OnContactDoubleTapped(object? sender, TappedEventArgs e)
|
||||
{
|
||||
if (DataContext is StudentDetailViewModel vm &&
|
||||
vm.ViewSelectedAddressCommand.CanExecute(null))
|
||||
vm.ViewSelectedAddressCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
using Avalonia.Controls;
|
||||
using LehrerApp.Desktop.ViewModels;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace LehrerApp.Desktop.Views;
|
||||
|
||||
public partial class SyncStatusBar : UserControl
|
||||
{
|
||||
public SyncStatusBar()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += (_, _) =>
|
||||
{
|
||||
if (DataContext is null)
|
||||
DataContext = App.Services.GetRequiredService<SyncStatusViewModel>();
|
||||
};
|
||||
}
|
||||
public SyncStatusBar() => InitializeComponent();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user