Refactor LoginPage to MVVM
This commit is contained in:
@@ -10,13 +10,13 @@
|
||||
Title="{Binding Title}">
|
||||
|
||||
|
||||
<ContentPage.BindingContext>
|
||||
<models:LoginViewModel />
|
||||
</ContentPage.BindingContext>
|
||||
<!-- BindingContext wird via DI im Code-Behind gesetzt -->
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<conv:StringVisibilityConverter x:Key="StringVisibilityConverter" />
|
||||
<conv:InverseBoolConverter x:Key="InverseBoolConverter" />
|
||||
<conv:EventArgsPassThroughConverter x:Key="EventArgsPassThroughConverter" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</HorizontalStackLayout>
|
||||
<Grid Grid.Column="1" ColumnDefinitions="*,50" ColumnSpacing="10">
|
||||
<Label Text="Login QR/manuell" VerticalOptions="Center" Grid.Column="0" />
|
||||
<Switch x:Name="LoginSwitch" IsToggled="False" Toggled="Switch_Toggled" VerticalOptions="Center"
|
||||
<Switch x:Name="LoginSwitch" IsToggled="{Binding IsManualMode}" VerticalOptions="Center"
|
||||
Grid.Column="1" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -47,25 +47,30 @@
|
||||
<Label x:Name="ServerLabel" Text="{Binding Server}"
|
||||
IsVisible="{Binding Server, Converter={StaticResource StringVisibilityConverter}}" />
|
||||
|
||||
<VerticalStackLayout x:Name="LoginQR" Margin="0,20,0,0">
|
||||
<VerticalStackLayout x:Name="LoginQR" Margin="0,20,0,0" IsVisible="{Binding IsManualMode, Converter={StaticResource InverseBoolConverter}}">
|
||||
<Label Text="Login mit QR-Code" FontSize="32" HorizontalOptions="Start" />
|
||||
<Label x:Name="Message" Text="{Binding Message}" Margin="0,15" />
|
||||
|
||||
<Border HeightRequest="300" Padding="0">
|
||||
<zxing:CameraBarcodeReaderView
|
||||
x:Name="barcodeScannerView"
|
||||
BarcodesDetected="BarcodesDetected"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
VerticalOptions="FillAndExpand" />
|
||||
VerticalOptions="FillAndExpand"
|
||||
IsDetecting="{Binding IsDetecting}">
|
||||
<zxing:CameraBarcodeReaderView.Behaviors>
|
||||
<toolkit:EventToCommandBehavior EventName="BarcodesDetected"
|
||||
Command="{Binding QrDetectedCommand}"
|
||||
EventArgsConverter="{StaticResource EventArgsPassThroughConverter}" />
|
||||
</zxing:CameraBarcodeReaderView.Behaviors>
|
||||
</zxing:CameraBarcodeReaderView>
|
||||
</Border>
|
||||
</VerticalStackLayout>
|
||||
|
||||
<VerticalStackLayout x:Name="LoginManual" Spacing="25">
|
||||
<VerticalStackLayout x:Name="LoginManual" Spacing="25" IsVisible="{Binding IsManualMode}">
|
||||
<Label Text="Manueller Login" FontSize="32" HorizontalOptions="Start" Margin="0, 20, 0, 0" />
|
||||
<Entry x:Name="UsernameEntry" Placeholder="Benutzername (Mailadresse)" Keyboard="Email" />
|
||||
<Entry x:Name="PasswordEntry" Placeholder="Passwort" IsPassword="True" />
|
||||
<Entry x:Name="ServerEntry" Placeholder="Server (gleich wie im Browser)" Keyboard="Url" />
|
||||
<Button Text="Login" Clicked="OnLoginButtonClicked"
|
||||
<Entry x:Name="UsernameEntry" Text="{Binding Username}" Placeholder="Benutzername (Mailadresse)" Keyboard="Email" />
|
||||
<Entry x:Name="PasswordEntry" Text="{Binding Password}" Placeholder="Passwort" IsPassword="True" />
|
||||
<Entry x:Name="ServerEntry" Text="{Binding Server}" Placeholder="Server (gleich wie im Browser)" Keyboard="Url" />
|
||||
<Button Text="Login" Command="{Binding LoginCommand}"
|
||||
TextColor="{AppThemeBinding Dark={StaticResource White}, Light={StaticResource White}}" />
|
||||
</VerticalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Jugenddienst_Stunden.Models;
|
||||
using Jugenddienst_Stunden.Types;
|
||||
using Jugenddienst_Stunden.ViewModels;
|
||||
using ZXing.Net.Maui;
|
||||
|
||||
|
||||
@@ -19,9 +20,38 @@ public partial class LoginPage : ContentPage {
|
||||
public LoginPage() {
|
||||
InitializeComponent();
|
||||
|
||||
// BindingContext via DI beziehen, falls nicht bereits gesetzt
|
||||
try {
|
||||
if (BindingContext is null) {
|
||||
var sp = Application.Current?.Handler?.MauiContext?.Services
|
||||
?? throw new InvalidOperationException("DI container ist nicht verfügbar.");
|
||||
BindingContext = sp.GetRequiredService<LoginViewModel>();
|
||||
}
|
||||
} catch (Exception) {
|
||||
// Ignorieren: Fallback bleibt leerer BindingContext
|
||||
}
|
||||
|
||||
if (BindingContext is LoginViewModel vm) {
|
||||
vm.AlertEvent += async (_, msg) => await DisplayAlert("Fehler:", msg, "OK");
|
||||
vm.InfoEvent += async (_, msg) => await DisplayAlert("Information:", msg, "OK");
|
||||
}
|
||||
|
||||
barcodeScannerView.Options =
|
||||
new BarcodeReaderOptions { Formats = BarcodeFormat.QrCode, AutoRotate = true, Multiple = false };
|
||||
|
||||
// Fallback-Verkabelung: Falls das EventToCommandBehavior in XAML nicht greift,
|
||||
// leiten wir das Kamera-Event manuell an das ViewModel-Command weiter.
|
||||
barcodeScannerView.BarcodesDetected += (s, e) => {
|
||||
if (BindingContext is LoginViewModel vm && vm.QrDetectedCommand is not null) {
|
||||
// Sicherstellen, dass die Command-Ausführung im UI-Thread erfolgt
|
||||
MainThread.BeginInvokeOnMainThread(async () => {
|
||||
if (vm.QrDetectedCommand.CanExecute(e)) {
|
||||
await vm.QrDetectedCommand.ExecuteAsync(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//if (BindingContext is LoginViewModel vm) {
|
||||
// vm.AlertEvent += Vm_AlertEvent;
|
||||
// vm.InfoEvent += Vm_InfoEvent;
|
||||
@@ -29,20 +59,7 @@ public partial class LoginPage : ContentPage {
|
||||
//}
|
||||
|
||||
//Zwischen manuellem und automatischem Login (mit QR-Code) umschalten und die Schalterstellung merken
|
||||
bool sqr = true;
|
||||
bool sma = false;
|
||||
if (Preferences.Default.Get("logintype", "") == "manual") {
|
||||
sqr = false;
|
||||
sma = true;
|
||||
LoginSwitch.IsToggled = true;
|
||||
Message.IsVisible = false;
|
||||
} else {
|
||||
LoginSwitch.IsToggled = false;
|
||||
Message.IsVisible = true;
|
||||
}
|
||||
|
||||
LoginQR.IsVisible = sqr;
|
||||
LoginManual.IsVisible = sma;
|
||||
// MVVM übernimmt Umschalten über IsManualMode im ViewModel; keine Code-Behind-Umschaltung mehr
|
||||
}
|
||||
|
||||
|
||||
@@ -102,13 +119,13 @@ public partial class LoginPage : ContentPage {
|
||||
base.OnDisappearing();
|
||||
|
||||
barcodeScannerView.CameraLocation = CameraLocation.Front;
|
||||
barcodeScannerView.IsDetecting = false;
|
||||
// IsDetecting wird via Binding vom ViewModel gesteuert
|
||||
}
|
||||
|
||||
protected override void OnAppearing() {
|
||||
base.OnAppearing();
|
||||
|
||||
barcodeScannerView.IsDetecting = true;
|
||||
// IsDetecting wird via Binding vom ViewModel gesteuert
|
||||
barcodeScannerView.CameraLocation = CameraLocation.Rear;
|
||||
}
|
||||
|
||||
@@ -175,21 +192,7 @@ public partial class LoginPage : ContentPage {
|
||||
}
|
||||
|
||||
//Zwischen manuellem und automatischem Login (mit QR-Code) umschalten und die Schalterstellung merken
|
||||
private void Switch_Toggled(object sender, ToggledEventArgs e) {
|
||||
var switcher = (Switch)sender;
|
||||
|
||||
if (switcher.IsToggled) {
|
||||
LoginQR.IsVisible = false;
|
||||
LoginManual.IsVisible = true;
|
||||
Message.IsVisible = false;
|
||||
Preferences.Default.Set("logintype", "manual");
|
||||
} else {
|
||||
LoginQR.IsVisible = true;
|
||||
LoginManual.IsVisible = false;
|
||||
Message.IsVisible = true;
|
||||
Preferences.Default.Set("logintype", "qr");
|
||||
}
|
||||
}
|
||||
// Umschalt-Logik erfolgt über Binding an IsManualMode im ViewModel
|
||||
|
||||
//private void Vm_AlertEvent(object? sender, string e) {
|
||||
// DisplayAlert("Fehler:", e, "OK");
|
||||
|
||||
Reference in New Issue
Block a user