Fixes the dependency loop.

This commit is contained in:
Dennis Brentjes
2026-02-02 20:52:05 +01:00
parent ed5f941ba8
commit 7e1928c3cb
7 changed files with 52 additions and 24 deletions

View File

@@ -27,6 +27,9 @@ public partial class App : Application
{ {
// Register all the services needed for the application to run // Register all the services needed for the application to run
var collection = new ServiceCollection(); var collection = new ServiceCollection();
new AppBootstrapper(collection, new RoutingState());
var state = new GamenightState(); var state = new GamenightState();
collection.AddSingleton(state); collection.AddSingleton(state);
@@ -38,7 +41,6 @@ public partial class App : Application
); );
collection.AddSingleton(gamenightApi); collection.AddSingleton(gamenightApi);
collection.AddSingleton<MainViewModel>(); collection.AddSingleton<MainViewModel>();
collection.AddSingleton<IScreen>(sp => sp.GetRequiredService<MainViewModel>());
collection.AddSingleton<HeaderViewModel>(); collection.AddSingleton<HeaderViewModel>();
collection.AddSingleton<SideBarViewModel>(); collection.AddSingleton<SideBarViewModel>();
collection.AddSingleton<GamenightsViewModel>(); collection.AddSingleton<GamenightsViewModel>();
@@ -51,6 +53,8 @@ public partial class App : Application
collection.AddSingleton<MainView>(); collection.AddSingleton<MainView>();
} }
RxApp.SuspensionHost.GetAppState<AppBootstrapper>();
ServiceProvider = collection.BuildServiceProvider(); ServiceProvider = collection.BuildServiceProvider();
var mainViewModel = ServiceProvider.GetRequiredService<MainViewModel>(); var mainViewModel = ServiceProvider.GetRequiredService<MainViewModel>();

View File

@@ -0,0 +1,26 @@
using ReactiveUI;
using Splat;
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
namespace Gamenight.Ui
{
public class AppBootstrapper : ReactiveObject, IScreen
{
public AppBootstrapper(ServiceCollection collection, RoutingState router)
{
Router = router ?? new RoutingState();
collection.AddSingleton<IScreen>(this);
}
public RoutingState Router { get; }
}
}

View File

@@ -16,9 +16,4 @@ public class GamenightsViewModel : ReactiveObject, IRoutableViewModel
GamenightApi = gamenightApi; GamenightApi = gamenightApi;
HostScreen = hostScreen; HostScreen = hostScreen;
} }
public GamenightsViewModel()
{
throw new NotImplementedException();
}
} }

View File

@@ -6,7 +6,7 @@ using ReactiveUI.SourceGenerators;
namespace Gamenight.Ui.ViewModels; namespace Gamenight.Ui.ViewModels;
public partial class MainViewModel : ReactiveObject, IScreen public partial class MainViewModel : ReactiveObject
{ {
[ObservableAsProperty] [ObservableAsProperty]
private string _greeting = "Welcome to Avalonia!"; private string _greeting = "Welcome to Avalonia!";
@@ -14,17 +14,19 @@ public partial class MainViewModel : ReactiveObject, IScreen
public HeaderViewModel HeaderViewModel { get; } public HeaderViewModel HeaderViewModel { get; }
public SideBarViewModel SideBarViewModel { get; } public SideBarViewModel SideBarViewModel { get; }
public RoutingState Router { get; } = new RoutingState();
[ObservableAsProperty] [ObservableAsProperty]
private IReactiveCommand _loginCommand; private IReactiveCommand _loginCommand;
public MainViewModel(IGamenightApi gamenightApi, HeaderViewModel headerViewModel, SideBarViewModel sideBarViewModel) [ObservableAsProperty]
private IScreen _screen;
public MainViewModel(IGamenightApi gamenightApi, IScreen screen, HeaderViewModel headerViewModel, SideBarViewModel sideBarViewModel)
{ {
GamenightApi = gamenightApi; GamenightApi = gamenightApi;
_screen = screen;
HeaderViewModel = headerViewModel; HeaderViewModel = headerViewModel;
SideBarViewModel = sideBarViewModel; SideBarViewModel = sideBarViewModel;
SideBarViewModel.Screen = this;
_loginCommand = ReactiveCommand.Create(Test); _loginCommand = ReactiveCommand.Create(Test);
} }

View File

@@ -6,6 +6,13 @@ namespace Gamenight.Ui.ViewModels;
public partial class SideBarViewModel : ReactiveObject public partial class SideBarViewModel : ReactiveObject
{ {
public SideBarViewModel(IScreen screen, GamenightsViewModel gamenightsViewModel)
{
Screen = screen;
PushViewModel = ReactiveCommand.CreateFromObservable((IRoutableViewModel x) => Screen.Router.Navigate.Execute(x));
GamenightsViewModel = gamenightsViewModel;
}
public IReactiveCommand<IRoutableViewModel, IRoutableViewModel> PushViewModel public IReactiveCommand<IRoutableViewModel, IRoutableViewModel> PushViewModel
{ {
get; get;
@@ -18,12 +25,5 @@ public partial class SideBarViewModel : ReactiveObject
set => this.RaiseAndSetIfChanged(ref field, value); set => this.RaiseAndSetIfChanged(ref field, value);
} }
public IScreen Screen { get; set; } private IScreen Screen { get; }
public SideBarViewModel(GamenightsViewModel gamenightsViewModel)
{
PushViewModel = ReactiveCommand.CreateFromObservable((IRoutableViewModel x) => Screen.Router.Navigate.Execute(x));
GamenightsViewModel = gamenightsViewModel;
}
} }

View File

@@ -6,9 +6,10 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Gamenight.Ui.Views.GamenightsView" x:Class="Gamenight.Ui.Views.GamenightsView"
x:DataType="vm:GamenightsViewModel"> x:DataType="vm:GamenightsViewModel">
<Design.DataContext> <Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE, <!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) --> to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:GamenightsViewModel /> <vm:GamenightsViewModel />
</Design.DataContext> </Design.DataContext>
<Label Content="LOL"></Label>
</UserControl> </UserControl>

View File

@@ -26,7 +26,7 @@
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<views:SideBarView Grid.Column="0" DataContext="{Binding SideBarViewModel}"/> <views:SideBarView Grid.Column="0" DataContext="{Binding SideBarViewModel}"/>
<reactiveUi:RoutedViewHost Grid.Column="1" Router="{Binding Router}"> <reactiveUi:RoutedViewHost Grid.Column="1" Router="{Binding Screen.Router}">
<reactiveUi:RoutedViewHost.DefaultContent> <reactiveUi:RoutedViewHost.DefaultContent>
<TextBlock Text="Default content" <TextBlock Text="Default content"
HorizontalAlignment="Center" HorizontalAlignment="Center"