Factories and Views
This commit is contained in:
parent
4e7dfc56a8
commit
2529b728ba
16 changed files with 188 additions and 4 deletions
|
|
@ -1,6 +1,7 @@
|
|||
using InkForge.Common.Controllers;
|
||||
using InkForge.Common.Data;
|
||||
using InkForge.Common.ViewModels;
|
||||
using InkForge.Common.ViewModels.Landing;
|
||||
using InkForge.Common.Views;
|
||||
using InkForge.Data;
|
||||
|
||||
|
|
@ -16,6 +17,8 @@ public static class InkForgeServiceCollections
|
|||
|
||||
services.AddDbContextFactory<NoteDbContext, NoteDbContextFactory>();
|
||||
|
||||
services.AddSingleton<LandingViewModel>();
|
||||
services.AddSingleton<LandingViewModelFactory>();
|
||||
services.AddSingleton<WorkspaceController>();
|
||||
|
||||
services.AddTransient<IViewFor<LandingViewModel>, LandingView>();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class TypeFactory<TFactory, T>
|
||||
where TFactory : struct, IObjectParameters<TFactory>
|
||||
{
|
||||
private static ObjectFactory<T>? s_objectFactory;
|
||||
|
||||
public static T Create(in TFactory factory, IServiceProvider serviceProvider)
|
||||
{
|
||||
s_objectFactory ??= ActivatorUtilities.CreateFactory<T>(TFactory.Types);
|
||||
return s_objectFactory(serviceProvider, (object[])factory);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IObjectParameters<T>
|
||||
where T : struct, IObjectParameters<T>
|
||||
{
|
||||
abstract static Type[] Types { get; }
|
||||
|
||||
abstract static implicit operator object[](in T self);
|
||||
}
|
||||
}
|
||||
10
app/InkForge.Common/ReactiveUI/RoutableReactiveObject.cs
Normal file
10
app/InkForge.Common/ReactiveUI/RoutableReactiveObject.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using ReactiveUI;
|
||||
|
||||
namespace InkForge.Common.ReactiveUI;
|
||||
|
||||
public abstract class RoutableReactiveObject(IScreen screen) : ReactiveObject, IRoutableViewModel
|
||||
{
|
||||
public abstract string? UrlPathSegment { get; }
|
||||
|
||||
public IScreen HostScreen => screen;
|
||||
}
|
||||
23
app/InkForge.Common/ReactiveUI/ViewModelFactory.cs
Normal file
23
app/InkForge.Common/ReactiveUI/ViewModelFactory.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace InkForge.Common.ReactiveUI;
|
||||
|
||||
public interface IViewModelFactory<T, TCreator>
|
||||
{
|
||||
abstract static ObjectFactory<T> CreateObjectFactory();
|
||||
|
||||
abstract static TCreator GetCreator(ObjectFactory<T> factory, IServiceProvider serviceProvider);
|
||||
}
|
||||
|
||||
public class ViewModelFactory<T, TFactory, TCreator>
|
||||
where TFactory : IViewModelFactory<T, TCreator>
|
||||
where TCreator : Delegate
|
||||
{
|
||||
private static ObjectFactory<T>? s_factory;
|
||||
|
||||
public TCreator CreateFactory(IServiceProvider serviceProvider)
|
||||
{
|
||||
s_factory ??= TFactory.CreateObjectFactory();
|
||||
return TFactory.GetCreator(s_factory, serviceProvider);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,8 +14,8 @@ public class AppViewModel : ReactiveObject
|
|||
set => this.RaiseAndSetIfChanged(ref _view, value);
|
||||
}
|
||||
|
||||
public AppViewModel(WorkspaceController workspace)
|
||||
public AppViewModel(WorkspaceController workspace, LandingViewModel landingViewModel)
|
||||
{
|
||||
View = new LandingViewModel();
|
||||
View = landingViewModel;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
using InkForge.Common.ReactiveUI;
|
||||
|
||||
using ReactiveUI;
|
||||
|
||||
namespace InkForge.Common.ViewModels.Landing;
|
||||
|
||||
public class CreateWorkspaceViewModel : LandingViewModelBase
|
||||
{
|
||||
public override string? UrlPathSegment => null;
|
||||
|
||||
public CreateWorkspaceViewModel(LandingViewModel landing) : base(landing)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
using InkForge.Common.ReactiveUI;
|
||||
|
||||
namespace InkForge.Common.ViewModels.Landing;
|
||||
|
||||
public abstract class LandingViewModelBase(LandingViewModel landing) : RoutableReactiveObject(landing)
|
||||
{
|
||||
public LandingViewModel Landing => landing;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace InkForge.Common.ViewModels.Landing;
|
||||
|
||||
public class LandingViewModelFactory(IServiceProvider serviceProvider)
|
||||
{
|
||||
public T Create<T>(LandingViewModel landing) where T : LandingViewModelBase
|
||||
{
|
||||
LandingViewModelsObjectParameters objectParameters = new(landing);
|
||||
return TypeFactory<LandingViewModelsObjectParameters, T>.Create(objectParameters, serviceProvider);
|
||||
}
|
||||
|
||||
readonly record struct LandingViewModelsObjectParameters(
|
||||
LandingViewModel Landing
|
||||
) : IObjectParameters<LandingViewModelsObjectParameters>
|
||||
{
|
||||
public static Type[] Types => [typeof(LandingViewModel)];
|
||||
|
||||
public static implicit operator object[](in LandingViewModelsObjectParameters self) => [self.Landing];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using InkForge.Common.ReactiveUI;
|
||||
|
||||
namespace InkForge.Common.ViewModels.Landing;
|
||||
|
||||
public class OpenRecentViewModel : LandingViewModelBase
|
||||
{
|
||||
public override string? UrlPathSegment => null;
|
||||
|
||||
public OpenRecentViewModel(LandingViewModel landing) : base(landing)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,28 @@
|
|||
using System.Reactive.Linq;
|
||||
|
||||
using InkForge.Common.ViewModels.Landing;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using ReactiveUI;
|
||||
|
||||
namespace InkForge.Common.ViewModels;
|
||||
|
||||
public class LandingViewModel : ReactiveObject
|
||||
public class LandingViewModel : ReactiveObject, IScreen
|
||||
{
|
||||
private readonly LandingViewModelFactory _factory;
|
||||
|
||||
public RoutingState Router { get; } = new();
|
||||
|
||||
public LandingViewModel(LandingViewModelFactory factory)
|
||||
{
|
||||
_factory = factory;
|
||||
|
||||
Router.CurrentViewModel.Where(x => x is null)
|
||||
.InvokeCommand<IRoutableViewModel>(Router.NavigateAndReset);
|
||||
}
|
||||
|
||||
public void Navigate<T>() where T : LandingViewModelBase
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:ifcvm="using:InkForge.Common.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
|
|
@ -9,5 +10,9 @@
|
|||
x:Class="InkForge.Common.Views.LandingView"
|
||||
x:DataType="ifcvm:LandingViewModel">
|
||||
<Grid RowDefinitions="Auto, *, Auto">
|
||||
<Label Content="InkForge"
|
||||
Grid.Row="0" />
|
||||
|
||||
<reactiveui:RoutedViewHost Router="{CompiledBinding Router}" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
x:Class="InkForge.Common.Views.LandingViews.CreateWorkspaceView">
|
||||
Welcome to Avalonia!
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using Avalonia.ReactiveUI;
|
||||
|
||||
using InkForge.Common.ViewModels.Landing;
|
||||
|
||||
namespace InkForge.Common.Views.LandingViews;
|
||||
|
||||
public partial class CreateWorkspaceView : ReactiveUserControl<CreateWorkspaceViewModel>
|
||||
{
|
||||
public CreateWorkspaceView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
10
app/InkForge.Common/Views/LandingViews/OpenRecentView.axaml
Normal file
10
app/InkForge.Common/Views/LandingViews/OpenRecentView.axaml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
x:Class="InkForge.Common.Views.LandingViews.OpenRecentView">
|
||||
Welcome to Avalonia!
|
||||
</UserControl>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using Avalonia.ReactiveUI;
|
||||
|
||||
using InkForge.Common.ViewModels.Landing;
|
||||
|
||||
namespace InkForge.Common.Views.LandingViews;
|
||||
|
||||
public partial class OpenRecentView : ReactiveUserControl<OpenRecentViewModel>
|
||||
{
|
||||
public OpenRecentView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ifcvm="using:InkForge.Common.ViewModels"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:ifcvm="using:InkForge.Common.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="800"
|
||||
d:DesignHeight="450"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue