feat: move mainwindow to core and add NavigationService

This commit is contained in:
2026-02-19 13:13:57 +03:00
parent 9cf8d7c909
commit 35e2397a29
8 changed files with 124 additions and 56 deletions
+30 -13
View File
@@ -5,6 +5,9 @@ using Avalonia.Threading;
using GSS2.Test.ViewModels; using GSS2.Test.ViewModels;
using GSS2.Test.Views; using GSS2.Test.Views;
using GSS2.UI.Core;
using GSS2.UI.Core.Services;
using GSS2.UI.Core.ViewModels;
namespace GSS2.Test; namespace GSS2.Test;
@@ -20,30 +23,44 @@ public partial class App : Application
if (ApplicationLifetime is null) if (ApplicationLifetime is null)
throw new InvalidOperationException("Application framework initialization cannot be fulfilled, ApplicationLifetime is null"); throw new InvalidOperationException("Application framework initialization cannot be fulfilled, ApplicationLifetime is null");
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) var loggerFactory = Program.ApplicationHost.Services.GetRequiredService<ILoggerFactory>();
var navigationService = Program.ApplicationHost.Services.GetRequiredService<NavigationService>();
switch (ApplicationLifetime)
{ {
case IClassicDesktopStyleApplicationLifetime desktop:
Console.WriteLine("Application running in classic style"); Console.WriteLine("Application running in classic style");
desktop.Startup += (_, _) => Program.ApplicationHost.RunAsync(); desktop.Startup += (_, _) => Program.ApplicationHost.RunAsync();
desktop.Exit += (_, _) => Program.ApplicationHost.StopAsync(); desktop.Exit += (_, _) => Program.ApplicationHost.StopAsync();
desktop.MainWindow = new MainWindow() var mainWindowViewModelLogger = loggerFactory.CreateLogger<MainWindowViewModel>();
var mainWindow = new MainWindow()
{ {
DataContext = Program.ApplicationHost.Services.GetRequiredService<MainWindowViewModel>() DataContext = new MainWindowViewModel(mainWindowViewModelLogger)
}; };
Program.ShutdownRequested += (_, _) => Dispatcher.UIThread.Invoke(() => desktop.MainWindow.Close()); desktop.MainWindow = mainWindow;
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleView) Program.ShutdownRequested += (_, _) => Dispatcher.UIThread.Invoke(() => desktop.MainWindow?.Close());
{ break;
case ISingleViewApplicationLifetime singleView:
Console.WriteLine("Application running in single view style"); Console.WriteLine("Application running in single view style");
var loggerFactory = Program.ApplicationHost.Services.GetRequiredService<ILoggerFactory>(); break;
var logger = loggerFactory.CreateLogger<MainView>();
singleView.MainView = new MainView(logger) default:
throw new InvalidOperationException($"Application framework initialization cannot be fulfilled, ApplicationLifetime has unknown type inherited from: {string.Join(", ", ApplicationLifetime.GetType().GetInterfaces().Select(i => i.FullName))}");
}
var mainViewLogger = loggerFactory.CreateLogger<MainView>();
var mainView = new MainView(mainViewLogger)
{ {
DataContext = Program.ApplicationHost.Services.GetRequiredService<MainViewModel>() DataContext = Program.ApplicationHost.Services.GetRequiredService<MainViewModel>()
}; };
} navigationService.NavigateTo(mainView);
else
throw new InvalidOperationException($"Application framework initialization cannot be fulfilled, ApplicationLifetime has unknown type inherited from: {string.Join(", ", ApplicationLifetime.GetType().GetInterfaces().Select(i => i.FullName))}");
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();
} }
} }
+4
View File
@@ -2,6 +2,9 @@ using GSS2.UI.Core.Views;
using GSS2.UI.Core.ViewModels; using GSS2.UI.Core.ViewModels;
using GSS2.Test.Views; using GSS2.Test.Views;
using GSS2.Test.ViewModels; using GSS2.Test.ViewModels;
using GSS2.UI.Core.Services;
using Avalonia;
namespace GSS2.Test; namespace GSS2.Test;
@@ -9,6 +12,7 @@ public static class DependencyInjectionHelper
{ {
public static IServiceCollection AddViewsAndModels(this IServiceCollection services) => public static IServiceCollection AddViewsAndModels(this IServiceCollection services) =>
services services
.AddSingleton<NavigationService>((_) => new NavigationService(Application.Current?.ApplicationLifetime))
.AddSingleton<MainWindowViewModel>() .AddSingleton<MainWindowViewModel>()
.AddSingleton<MainView>() .AddSingleton<MainView>()
.AddSingleton<MainViewModel>() .AddSingleton<MainViewModel>()
-11
View File
@@ -1,11 +0,0 @@
using Avalonia.Controls;
namespace GSS2.Test;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
+4 -1
View File
@@ -11,6 +11,7 @@ public partial class MainViewModel : ViewModelBase
private readonly ILogger<MainViewModel> _logger; private readonly ILogger<MainViewModel> _logger;
private readonly CameraService _cameraService; private readonly CameraService _cameraService;
private readonly IlluminatorService _illuminatorService; private readonly IlluminatorService _illuminatorService;
[ObservableProperty] private CameraViewModel _cameraViewModel; [ObservableProperty] private CameraViewModel _cameraViewModel;
[ObservableProperty] private ResourcesViewModel _resourcesViewModel; [ObservableProperty] private ResourcesViewModel _resourcesViewModel;
[ObservableProperty] private IlluminatorControllerViewModel _illuminatorControllerViewModel; [ObservableProperty] private IlluminatorControllerViewModel _illuminatorControllerViewModel;
@@ -28,6 +29,8 @@ public partial class MainViewModel : ViewModelBase
public MainViewModel(ILogger<MainViewModel> logger, CameraViewModel cameraViewModel, ResourcesViewModel resourcesViewModel, IlluminatorControllerViewModel illuminatorControllerViewModel, CameraService cameraService, IlluminatorService illuminatorService) public MainViewModel(ILogger<MainViewModel> logger, CameraViewModel cameraViewModel, ResourcesViewModel resourcesViewModel, IlluminatorControllerViewModel illuminatorControllerViewModel, CameraService cameraService, IlluminatorService illuminatorService)
{ {
_logger = logger; _logger = logger;
_logger.LogInformation("Initialization");
_cameraService = cameraService; _cameraService = cameraService;
_illuminatorService = illuminatorService; _illuminatorService = illuminatorService;
CameraViewModel = cameraViewModel; CameraViewModel = cameraViewModel;
@@ -53,6 +56,6 @@ public partial class MainViewModel : ViewModelBase
ButtonUpClick = new RelayCommand(() => CurrentIndex--); ButtonUpClick = new RelayCommand(() => CurrentIndex--);
ButtonDownClick = new RelayCommand(() => CurrentIndex++); ButtonDownClick = new RelayCommand(() => CurrentIndex++);
_logger.LogInformation("{} initialized", nameof(MainViewModel)); _logger.LogInformation("Initialized");
} }
} }
@@ -1,20 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
using GSS2.UI.Core.ViewModels;
namespace GSS2.Test.ViewModels;
public partial class MainWindowViewModel : ViewModelBase
{
[ObservableProperty] private string _title;
[ObservableProperty] private MainViewModel _mainViewModel;
private readonly ILogger<MainWindowViewModel> _logger;
public MainWindowViewModel(ILogger<MainWindowViewModel> logger, MainViewModel mainViewModel)
{
_logger = logger;
MainViewModel = mainViewModel;
Title = "GSS2.Test";
_logger.LogInformation("{} initialized", nameof(MainWindowViewModel));
}
}
@@ -1,13 +1,13 @@
<Window <Window
x:Class="GSS2.Test.MainWindow" x:Class="GSS2.UI.Core.MainWindow"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GSS2.Test.ViewModels" xmlns:vm="using:GSS2.UI.Core.ViewModels"
Title="{Binding Title}" Title="{Binding Title}"
x:DataType="vm:MainWindowViewModel"> x:DataType="vm:MainWindowViewModel">
<ContentControl Content="{Binding MainViewModel}" /> <ContentControl x:Name="MainContent" />
</Window> </Window>
+16
View File
@@ -0,0 +1,16 @@
using Avalonia.Controls;
namespace GSS2.UI.Core;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void SetControl(UserControl control)
{
MainContent.Content = control;
}
}
+59
View File
@@ -0,0 +1,59 @@
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
namespace GSS2.UI.Core.Services;
public class NavigationService
{
private readonly Stack<UserControl> _navigateControls = new Stack<UserControl>();
private readonly IApplicationLifetime? _applicationLifetime;
public NavigationService(IApplicationLifetime? applicationLifetime)
{
_applicationLifetime = applicationLifetime;
}
public void NavigateTo(UserControl control)
{
_navigateControls.Push(control);
switch (_applicationLifetime)
{
case IClassicDesktopStyleApplicationLifetime desktop
when desktop.MainWindow is MainWindow mainWindow:
mainWindow.SetControl(control);
break;
case ISingleViewApplicationLifetime singleView:
singleView.MainView = control;
break;
}
}
public void NavigateBack()
{
if (_navigateControls.Count <= 1)
return;
var lastControl = _navigateControls.Pop();
var control = _navigateControls.Peek();
switch (_applicationLifetime)
{
case IClassicDesktopStyleApplicationLifetime desktop
when desktop.MainWindow is MainWindow mainWindow:
mainWindow.SetControl(control);
break;
case ISingleViewApplicationLifetime singleView:
singleView.MainView = control;
break;
}
if (lastControl is IDisposable disposable)
disposable.Dispose();
}
}