From 2aeb4d1b54569429787f36e21804075230da8549 Mon Sep 17 00:00:00 2001 From: TheXamlGuy Date: Thu, 8 Feb 2024 22:16:58 +0000 Subject: [PATCH] Bunch of insane work --- Hyperbar.UI.Windows/DataTemplateConverter.cs | 15 -- Hyperbar.UI.Windows/TemplateFactory.cs | 23 --- Hyperbar.UI.Windows/TemplateGenerator.cs | 36 ----- .../TemplateGeneratorControl.cs | 22 --- .../ViewModelTemplatePresenter.cs | 23 +++ .../ViewModelTemplateSelector.cs | 92 +++++++++++ Hyperbar.UI.Windows/WindowExtensions.cs | 16 ++ .../ContextualWidgetViewModel.cs | 7 +- .../MediaButtonViewModel.cs | 7 +- .../MediaControllerView.xaml | 26 ++- .../MediaControllerViewModel.cs | 12 +- .../MediaControllerWidgetView.xaml | 4 +- .../MediaControllerWidgetViewModel.cs | 14 +- .../MediaInformationViewModel.cs | 7 +- .../PrimaryWidgetViewModel.cs | 10 +- .../WidgetComponentFactory.cs | 1 - .../IServiceCollectionExtensions.cs | 3 +- Hyperbar.Widget.Windows/WidgetView.xaml | 4 +- .../IServiceCollectionExtensions.cs | 6 +- Hyperbar.Widget/WidgetButtonViewModel.cs | 7 +- Hyperbar.Widget/WidgetComponentViewModel.cs | 17 +- Hyperbar.Widget/WidgetMenuViewModel.cs | 7 +- Hyperbar.Widget/WidgetSplitButtonViewModel.cs | 7 +- Hyperbar.Windows/App.xaml | 2 +- Hyperbar.Windows/App.xaml.cs | 7 +- Hyperbar.Windows/ApplicationBarView.xaml | 6 +- Hyperbar.Windows/ApplicationBarViewModel.cs | 10 +- .../GeneralSettingsNavigationView.xaml | 6 + .../GeneralSettingsNavigationView.xaml.cs | 10 ++ .../GeneralSettingsNavigationViewModel.cs | 10 ++ Hyperbar.Windows/Hyperbar.Windows.csproj | 12 ++ Hyperbar.Windows/PrimaryView.xaml | 4 +- Hyperbar.Windows/PrimaryViewModel.cs | 10 +- Hyperbar.Windows/SecondaryView.xaml | 4 +- Hyperbar.Windows/SecondaryViewModel.cs | 10 +- Hyperbar.Windows/SettingsButtonViewModel.cs | 10 +- Hyperbar.Windows/SettingsView.xaml | 12 +- Hyperbar.Windows/SettingsView.xaml.cs | 13 +- Hyperbar.Windows/SettingsViewModel.cs | 16 +- Hyperbar.Windows/WidgetNavigationViewModel.cs | 10 ++ .../WidgetSettingsNavigationView.xaml | 6 + .../WidgetSettingsNavigationView.xaml.cs | 10 ++ .../WidgetSettingsNavigationViewModel.cs | 11 ++ .../IServiceCollectionExtensions.cs | 4 +- Hyperbar/Lifecycles/INavigationViewModel.cs | 7 + Hyperbar/Lifecycles/IObservableViewModel.cs | 16 +- Hyperbar/Lifecycles/NavigateHandler.cs | 8 +- Hyperbar/Lifecycles/NavigationViewModel.cs | 22 ++- .../ObservableCollectionViewModel.cs | 153 +++++++++--------- Hyperbar/Lifecycles/ObservableViewModel.cs | 37 ++++- .../Templates/ContentTemplateDescriptor.cs | 11 -- Hyperbar/Templates/ITemplatedViewModel.cs | 6 - ...tor.cs => IViewModelTemplateDescriptor.cs} | 6 +- .../IViewModelTemplateDescriptorProvider.cs | 6 + .../IViewModelTemplateFactory.cs} | 2 +- .../Templates/ViewModelTemplateDescriptor.cs | 11 ++ .../ViewModelTemplateDescriptorProvider.cs | 16 ++ .../Templates/ViewModelTemplateFactory.cs | 23 +++ 58 files changed, 547 insertions(+), 326 deletions(-) delete mode 100644 Hyperbar.UI.Windows/DataTemplateConverter.cs delete mode 100644 Hyperbar.UI.Windows/TemplateFactory.cs delete mode 100644 Hyperbar.UI.Windows/TemplateGenerator.cs delete mode 100644 Hyperbar.UI.Windows/TemplateGeneratorControl.cs create mode 100644 Hyperbar.UI.Windows/ViewModelTemplatePresenter.cs create mode 100644 Hyperbar.UI.Windows/ViewModelTemplateSelector.cs create mode 100644 Hyperbar.Windows/GeneralSettingsNavigationView.xaml create mode 100644 Hyperbar.Windows/GeneralSettingsNavigationView.xaml.cs create mode 100644 Hyperbar.Windows/GeneralSettingsNavigationViewModel.cs create mode 100644 Hyperbar.Windows/WidgetNavigationViewModel.cs create mode 100644 Hyperbar.Windows/WidgetSettingsNavigationView.xaml create mode 100644 Hyperbar.Windows/WidgetSettingsNavigationView.xaml.cs create mode 100644 Hyperbar.Windows/WidgetSettingsNavigationViewModel.cs create mode 100644 Hyperbar/Lifecycles/INavigationViewModel.cs delete mode 100644 Hyperbar/Templates/ContentTemplateDescriptor.cs delete mode 100644 Hyperbar/Templates/ITemplatedViewModel.cs rename Hyperbar/Templates/{IContentTemplateDescriptor.cs => IViewModelTemplateDescriptor.cs} (53%) create mode 100644 Hyperbar/Templates/IViewModelTemplateDescriptorProvider.cs rename Hyperbar/{Lifecycles/ITemplateFactory.cs => Templates/IViewModelTemplateFactory.cs} (57%) create mode 100644 Hyperbar/Templates/ViewModelTemplateDescriptor.cs create mode 100644 Hyperbar/Templates/ViewModelTemplateDescriptorProvider.cs create mode 100644 Hyperbar/Templates/ViewModelTemplateFactory.cs diff --git a/Hyperbar.UI.Windows/DataTemplateConverter.cs b/Hyperbar.UI.Windows/DataTemplateConverter.cs deleted file mode 100644 index 58e9dd4..0000000 --- a/Hyperbar.UI.Windows/DataTemplateConverter.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace Hyperbar.UI.Windows; - -public class DataTemplateConverter : - ValueConverter -{ - protected override DataTemplateSelector? ConvertTo(object value, - Type? targetType, - object? parameter, - string? language) - { - return new TemplateGenerator(); - } -} \ No newline at end of file diff --git a/Hyperbar.UI.Windows/TemplateFactory.cs b/Hyperbar.UI.Windows/TemplateFactory.cs deleted file mode 100644 index f01c01b..0000000 --- a/Hyperbar.UI.Windows/TemplateFactory.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Hyperbar.UI.Windows; - -public class TemplateFactory(IEnumerable descriptors, - IServiceProvider provider) : - ITemplateFactory -{ - public object? Create(object key) - { - if (descriptors.FirstOrDefault(x => x.Key == key) - is IContentTemplateDescriptor descriptor) - { - if (provider.GetRequiredKeyedService(descriptor.TemplateType, - descriptor.Key) is { } template) - { - return template; - } - } - - return default; - } -} \ No newline at end of file diff --git a/Hyperbar.UI.Windows/TemplateGenerator.cs b/Hyperbar.UI.Windows/TemplateGenerator.cs deleted file mode 100644 index 63849b3..0000000 --- a/Hyperbar.UI.Windows/TemplateGenerator.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Markup; - -namespace Hyperbar.UI.Windows; - -public class TemplateGenerator : DataTemplateSelector -{ - protected override DataTemplate SelectTemplateCore(object item) - { - string xamlString = @" - - - "; - - return (DataTemplate)XamlReader.Load(xamlString); - } - - protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) - { - string xamlString = @" - - - "; - - return (DataTemplate)XamlReader.Load(xamlString); - } -} diff --git a/Hyperbar.UI.Windows/TemplateGeneratorControl.cs b/Hyperbar.UI.Windows/TemplateGeneratorControl.cs deleted file mode 100644 index 2185a28..0000000 --- a/Hyperbar.UI.Windows/TemplateGeneratorControl.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace Hyperbar.UI.Windows; - -public class TemplateGeneratorControl : - ContentControl -{ - public TemplateGeneratorControl() - { - DataContextChanged += OnDataContextChanged; - } - - private void OnDataContextChanged(FrameworkElement sender, - DataContextChangedEventArgs args) - { - if (DataContext is ITemplatedViewModel templatedViewModel) - { - Content = templatedViewModel.TemplateFactory.Create(DataContext.GetType().Name); - } - } -} \ No newline at end of file diff --git a/Hyperbar.UI.Windows/ViewModelTemplatePresenter.cs b/Hyperbar.UI.Windows/ViewModelTemplatePresenter.cs new file mode 100644 index 0000000..2462c27 --- /dev/null +++ b/Hyperbar.UI.Windows/ViewModelTemplatePresenter.cs @@ -0,0 +1,23 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +namespace Hyperbar.UI.Windows; + +public class ViewModelTemplatePresenter : + ContentPresenter +{ + public ViewModelTemplatePresenter() + { + DataContextChanged += OnDataContextChanged; + } + + private void OnDataContextChanged(FrameworkElement sender, + DataContextChangedEventArgs args) + { + //if (DataContext is IViewModelTemplate templatedViewModel) + //{ + // Content = templatedViewModel.TemplateFactory + // .Create(DataContext.GetType().Name); + //} + } +} \ No newline at end of file diff --git a/Hyperbar.UI.Windows/ViewModelTemplateSelector.cs b/Hyperbar.UI.Windows/ViewModelTemplateSelector.cs new file mode 100644 index 0000000..d3d675b --- /dev/null +++ b/Hyperbar.UI.Windows/ViewModelTemplateSelector.cs @@ -0,0 +1,92 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Markup; + +namespace Hyperbar.UI.Windows; + +public class ImplicitTemplate : + MarkupExtension +{ + protected override object ProvideValue(IXamlServiceProvider serviceProvider) => + new ImplicitTemplateSelector(); + + internal class ImplicitTemplateSelector : + DataTemplateSelector + { + protected override DataTemplate SelectTemplateCore(object item, + DependencyObject container) + { + + + string xamlString = @" + + + "; + + return (DataTemplate)XamlReader.Load(xamlString); + } + } +} + +public class ViewModelTemplate : + MarkupExtension +{ + protected override object ProvideValue(IXamlServiceProvider serviceProvider) => + new ViewModelTemplateSelector(); + + internal class ViewModelTemplateSelector : + DataTemplateSelector + { + protected override DataTemplate SelectTemplateCore(object item) + { + if (item is IObservableViewModel observableViewModel) + { + if (observableViewModel.ServiceProvider.GetService() + is ViewModelTemplateDescriptorProvider descriptors) + { + if (descriptors.Get(item.GetType().Name) is IViewModelTemplateDescriptor descriptor) + { + string xamlString = @$" + + + "; + + return (DataTemplate)XamlReader.Load(xamlString); + } + } + } + + return new DataTemplate(); + } + + protected override DataTemplate SelectTemplateCore(object item, + DependencyObject container) + { + if (item is IObservableViewModel observableViewModel) + { + if (observableViewModel.ServiceProvider.GetService() + is ViewModelTemplateDescriptorProvider descriptors) + { + if (descriptors.Get(item.GetType().Name) is IViewModelTemplateDescriptor descriptor) + { + string xamlString = @$" + + + "; + + return (DataTemplate)XamlReader.Load(xamlString); + } + } + } + + return new DataTemplate(); + } + } +} diff --git a/Hyperbar.UI.Windows/WindowExtensions.cs b/Hyperbar.UI.Windows/WindowExtensions.cs index ab7144f..60e4f32 100644 --- a/Hyperbar.UI.Windows/WindowExtensions.cs +++ b/Hyperbar.UI.Windows/WindowExtensions.cs @@ -1,11 +1,17 @@ using Hyperbar.Interop.Windows; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; using Windows.Graphics; using WinRT.Interop; namespace Hyperbar.UI.Windows; +public class NavigationItemTemplateSelector : + DataTemplateSelector +{ + +} public static class WindowExtensions { public static WindowMessageListener CreateMessageListener(this Window window) => @@ -36,6 +42,16 @@ public static class WindowExtensions public static void SetStyle(this Window window, ExtendedWindowStyle style) => window.GetHandle().SetExtendedWindowStyle(style); + public static void TitleBarConfiguration(this Window window, + Action titleBarDelegate) + { + AppWindow appWindow = window.AppWindow; + if (appWindow.TitleBar is AppWindowTitleBar titleBar) + { + titleBarDelegate.Invoke(titleBar); + } + } + public static void SetTopMost(this Window window, bool value) { diff --git a/Hyperbar.Widget.Contextual.Windows/ContextualWidgetViewModel.cs b/Hyperbar.Widget.Contextual.Windows/ContextualWidgetViewModel.cs index e253477..2868c2b 100644 --- a/Hyperbar.Widget.Contextual.Windows/ContextualWidgetViewModel.cs +++ b/Hyperbar.Widget.Contextual.Windows/ContextualWidgetViewModel.cs @@ -1,13 +1,12 @@ namespace Hyperbar.Widget.Contextual.Windows; -public class ContextualWidgetViewModel(ITemplateFactory templateFactory, +public class ContextualWidgetViewModel(IViewModelTemplateFactory templateFactory, IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, IEnumerable items) : ObservableCollectionViewModel(serviceFactory, mediator, disposer, items), - IWidgetViewModel, - ITemplatedViewModel + IWidgetViewModel { - public ITemplateFactory TemplateFactory => templateFactory; + public IViewModelTemplateFactory TemplateFactory => templateFactory; } \ No newline at end of file diff --git a/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs index 50508f3..4fac719 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs @@ -3,12 +3,13 @@ using CommunityToolkit.Mvvm.Input; namespace Hyperbar.Widget.MediaController.Windows; -public partial class MediaButtonViewModel(IServiceFactory serviceFactory, +public partial class MediaButtonViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - ITemplateFactory templateFactory, + IViewModelTemplateFactory templateFactory, IRelayCommand invokeCommand) : - WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory), + WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer, templateFactory), INotificationHandler>>, IMediaButtonViewModel { diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerView.xaml b/Hyperbar.Widget.MediaController.Windows/MediaControllerView.xaml index 6a0cfe1..d04e50d 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerView.xaml +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerView.xaml @@ -3,18 +3,16 @@ x:Class="Hyperbar.Widget.MediaController.Windows.MediaControllerView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:windows="using:Hyperbar.UI.Windows"> - - - - - - - - - + xmlns:ui="using:Hyperbar.UI.Windows"> + + + + + + + diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs index 203c06f..ed1cb29 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs @@ -2,17 +2,15 @@ namespace Hyperbar.Widget.MediaController.Windows; - - [NotificationHandler(nameof(MediaControllerViewModel))] public class MediaControllerViewModel : - ObservableCollectionViewModel, - ITemplatedViewModel + ObservableCollectionViewModel { - public MediaControllerViewModel(ITemplateFactory templateFactory, + public MediaControllerViewModel(IViewModelTemplateFactory templateFactory, + IServiceProvider serviceProvider, IServiceFactory serviceFactory, IMediator mediator, - IDisposer disposer) : base(serviceFactory, mediator, disposer) + IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer) { TemplateFactory = templateFactory; @@ -28,5 +26,5 @@ public class MediaControllerViewModel : await mediator.PublishAsync>())); } - public ITemplateFactory TemplateFactory { get; set; } + public IViewModelTemplateFactory TemplateFactory { get; set; } } \ No newline at end of file diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetView.xaml b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetView.xaml index fe77d80..efb1c43 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetView.xaml +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetView.xaml @@ -3,9 +3,9 @@ x:Class="Hyperbar.Widget.MediaController.Windows.MediaControllerWidgetView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:windows="using:Hyperbar.UI.Windows"> + xmlns:ui="using:Hyperbar.UI.Windows"> diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetViewModel.cs index 754a943..bc494cc 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetViewModel.cs @@ -1,15 +1,13 @@ -using Hyperbar.Widget; +namespace Hyperbar.Widget.MediaController.Windows; -namespace Hyperbar.Widget.MediaController.Windows; - -public class MediaControllerWidgetViewModel(ITemplateFactory templateFactory, +public class MediaControllerWidgetViewModel(IViewModelTemplateFactory templateFactory, + IServiceProvider serviceProvider, IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, IEnumerable items) : - ObservableCollectionViewModel(serviceFactory, mediator, disposer, items), - IWidgetViewModel, - ITemplatedViewModel + ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer, items), + IWidgetViewModel { - public ITemplateFactory TemplateFactory => templateFactory; + public IViewModelTemplateFactory TemplateFactory => templateFactory; } \ No newline at end of file diff --git a/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs index 5982798..03d67b2 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs @@ -2,11 +2,12 @@ namespace Hyperbar.Widget.MediaController.Windows; -public partial class MediaInformationViewModel(IServiceFactory serviceFactory, +public partial class MediaInformationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - ITemplateFactory templateFactory) : - WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory), + IViewModelTemplateFactory templateFactory) : + WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer, templateFactory), INotificationHandler> { [ObservableProperty] diff --git a/Hyperbar.Widget.Primary.Windows/PrimaryWidgetViewModel.cs b/Hyperbar.Widget.Primary.Windows/PrimaryWidgetViewModel.cs index 2186f0e..045d7a6 100644 --- a/Hyperbar.Widget.Primary.Windows/PrimaryWidgetViewModel.cs +++ b/Hyperbar.Widget.Primary.Windows/PrimaryWidgetViewModel.cs @@ -3,13 +3,13 @@ namespace Hyperbar.Widget.Primary.Windows; [NotificationHandler(nameof(PrimaryWidgetViewModel))] -public class PrimaryWidgetViewModel(ITemplateFactory templateFactory, +public class PrimaryWidgetViewModel(IViewModelTemplateFactory templateFactory, + IServiceProvider serviceProvider, IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer) : - ObservableCollectionViewModel(serviceFactory, mediator, disposer), - IWidgetViewModel, - ITemplatedViewModel + ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer), + IWidgetViewModel { - public ITemplateFactory TemplateFactory => templateFactory; + public IViewModelTemplateFactory TemplateFactory => templateFactory; } \ No newline at end of file diff --git a/Hyperbar.Widget.Primary.Windows/WidgetComponentFactory.cs b/Hyperbar.Widget.Primary.Windows/WidgetComponentFactory.cs index 1545b01..1506d0b 100644 --- a/Hyperbar.Widget.Primary.Windows/WidgetComponentFactory.cs +++ b/Hyperbar.Widget.Primary.Windows/WidgetComponentFactory.cs @@ -1,5 +1,4 @@ using CommunityToolkit.Mvvm.Input; -using Hyperbar.Widget; namespace Hyperbar.Widget.Primary.Windows; diff --git a/Hyperbar.Widget.Windows/IServiceCollectionExtensions.cs b/Hyperbar.Widget.Windows/IServiceCollectionExtensions.cs index cc7d2d2..6de350d 100644 --- a/Hyperbar.Widget.Windows/IServiceCollectionExtensions.cs +++ b/Hyperbar.Widget.Windows/IServiceCollectionExtensions.cs @@ -19,7 +19,8 @@ public static class IServiceCollectionExtensions services.AddSingleton(provider.GetRequiredService>()); services.AddSingleton(provider.GetRequiredService()); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddScoped(); services.AddHandler(); diff --git a/Hyperbar.Widget.Windows/WidgetView.xaml b/Hyperbar.Widget.Windows/WidgetView.xaml index d0b0bb1..40e992c 100644 --- a/Hyperbar.Widget.Windows/WidgetView.xaml +++ b/Hyperbar.Widget.Windows/WidgetView.xaml @@ -5,9 +5,9 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:interactions="using:Microsoft.Xaml.Interactions.Core" xmlns:interactivity="using:Microsoft.Xaml.Interactivity" - xmlns:windows="using:Hyperbar.UI.Windows"> + xmlns:ui="using:Hyperbar.UI.Windows"> - + diff --git a/Hyperbar.Widget/IServiceCollectionExtensions.cs b/Hyperbar.Widget/IServiceCollectionExtensions.cs index f8903fc..78b5c23 100644 --- a/Hyperbar.Widget/IServiceCollectionExtensions.cs +++ b/Hyperbar.Widget/IServiceCollectionExtensions.cs @@ -33,7 +33,7 @@ public static class IServiceCollectionExtensions services.AddKeyedTransient(typeof(IWidgetViewModel), key, contentType); services.TryAddKeyedTransient(key, (provider, key) => provider.GetService()!); - services.AddTransient(provider => new ContentTemplateDescriptor { ContentType = contentType, TemplateType = templateType, Key = key }); + services.AddTransient(provider => new ViewModelTemplateDescriptor { ViewModelType = contentType, TemplateType = templateType, Key = key }); return services; } @@ -54,8 +54,8 @@ public static class IServiceCollectionExtensions services.AddKeyedTransient(typeof(IWidgetViewModel), key, contentType); services.TryAddKeyedTransient(templateType, key); - services.AddTransient(provider => - new ContentTemplateDescriptor { ContentType = contentType, + services.AddTransient(provider => + new ViewModelTemplateDescriptor { ViewModelType = contentType, TemplateType = templateType, Key = key }); return services; diff --git a/Hyperbar.Widget/WidgetButtonViewModel.cs b/Hyperbar.Widget/WidgetButtonViewModel.cs index 3969098..a729d9b 100644 --- a/Hyperbar.Widget/WidgetButtonViewModel.cs +++ b/Hyperbar.Widget/WidgetButtonViewModel.cs @@ -4,14 +4,15 @@ using CommunityToolkit.Mvvm.Input; namespace Hyperbar.Widget; [NotificationHandler(nameof(Id))] -public partial class WidgetButtonViewModel(IServiceFactory serviceFactory, +public partial class WidgetButtonViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - ITemplateFactory templateFactory, + IViewModelTemplateFactory templateFactory, Guid id, string? text = null, string? icon = null, - RelayCommand? invokeCommand = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory) + RelayCommand? invokeCommand = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer, templateFactory) { [ObservableProperty] private string? icon = icon; diff --git a/Hyperbar.Widget/WidgetComponentViewModel.cs b/Hyperbar.Widget/WidgetComponentViewModel.cs index 798f298..a2731c3 100644 --- a/Hyperbar.Widget/WidgetComponentViewModel.cs +++ b/Hyperbar.Widget/WidgetComponentViewModel.cs @@ -2,25 +2,26 @@ public partial class WidgetComponentViewModel : ObservableCollectionViewModel, - IWidgetComponentViewModel, - ITemplatedViewModel + IWidgetComponentViewModel { - public WidgetComponentViewModel(IServiceFactory serviceFactory, + public WidgetComponentViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - ITemplateFactory templateFactory, - IEnumerable items) : base(serviceFactory, mediator, disposer, items) + IViewModelTemplateFactory templateFactory, + IEnumerable items) : base(serviceProvider, serviceFactory, mediator, disposer, items) { TemplateFactory = templateFactory; } - public WidgetComponentViewModel(IServiceFactory serviceFactory, + public WidgetComponentViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - ITemplateFactory templateFactory) : base(serviceFactory, mediator, disposer) + IViewModelTemplateFactory templateFactory) : base(serviceProvider, serviceFactory, mediator, disposer) { TemplateFactory = templateFactory; } - public ITemplateFactory TemplateFactory { get; private set; } + public IViewModelTemplateFactory TemplateFactory { get; private set; } } \ No newline at end of file diff --git a/Hyperbar.Widget/WidgetMenuViewModel.cs b/Hyperbar.Widget/WidgetMenuViewModel.cs index 2215470..b5dc32b 100644 --- a/Hyperbar.Widget/WidgetMenuViewModel.cs +++ b/Hyperbar.Widget/WidgetMenuViewModel.cs @@ -4,14 +4,15 @@ using CommunityToolkit.Mvvm.Input; namespace Hyperbar.Widget; [NotificationHandler(nameof(Id))] -public partial class WidgetMenuViewModel(IServiceFactory serviceFactory, +public partial class WidgetMenuViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - ITemplateFactory templateFactory, + IViewModelTemplateFactory templateFactory, Guid id = default, string? text = null, string? icon = null, - RelayCommand? command = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory) + RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer, templateFactory) { [ObservableProperty] private IRelayCommand? click = command; diff --git a/Hyperbar.Widget/WidgetSplitButtonViewModel.cs b/Hyperbar.Widget/WidgetSplitButtonViewModel.cs index 99d6117..406e61e 100644 --- a/Hyperbar.Widget/WidgetSplitButtonViewModel.cs +++ b/Hyperbar.Widget/WidgetSplitButtonViewModel.cs @@ -4,15 +4,16 @@ using CommunityToolkit.Mvvm.Input; namespace Hyperbar.Widget; [NotificationHandler(nameof(Id))] -public partial class WidgetSplitButtonViewModel(IServiceFactory serviceFactory, +public partial class WidgetSplitButtonViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - ITemplateFactory templateFactory, + IViewModelTemplateFactory templateFactory, IEnumerable items, Guid id = default, string? text = null, string? icon = null, - RelayCommand? command = null) : WidgetComponentViewModel(serviceFactory, mediator, disposer, templateFactory, items) + RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer, templateFactory, items) { [ObservableProperty] private IRelayCommand? click = command; diff --git a/Hyperbar.Windows/App.xaml b/Hyperbar.Windows/App.xaml index 1aaf4ee..eda95de 100644 --- a/Hyperbar.Windows/App.xaml +++ b/Hyperbar.Windows/App.xaml @@ -10,7 +10,7 @@ - + diff --git a/Hyperbar.Windows/App.xaml.cs b/Hyperbar.Windows/App.xaml.cs index a7ffcc3..67107e6 100644 --- a/Hyperbar.Windows/App.xaml.cs +++ b/Hyperbar.Windows/App.xaml.cs @@ -37,7 +37,9 @@ public partial class App : services.AddHostedService(); services.AddSingleton(new Dispatcher(DispatcherQueue.GetForCurrentThread())); - services.AddTransient(); + + services.AddTransient(); + services.AddTransient(); services.AddHandler(); services.AddConfiguration(args => @@ -55,6 +57,9 @@ public partial class App : services.AddContentTemplate(); services.AddContentTemplate("Settings"); + services.AddContentTemplate(); + services.AddContentTemplate(); + services.AddTransient(); }) .Build(); diff --git a/Hyperbar.Windows/ApplicationBarView.xaml b/Hyperbar.Windows/ApplicationBarView.xaml index 1eda1e8..e3aca94 100644 --- a/Hyperbar.Windows/ApplicationBarView.xaml +++ b/Hyperbar.Windows/ApplicationBarView.xaml @@ -3,7 +3,7 @@ x:Class="Hyperbar.Windows.ApplicationBarView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:windows="using:Hyperbar.UI.Windows"> + xmlns:ui="using:Hyperbar.UI.Windows"> @@ -17,7 +17,7 @@ @@ -36,7 +36,7 @@ diff --git a/Hyperbar.Windows/ApplicationBarViewModel.cs b/Hyperbar.Windows/ApplicationBarViewModel.cs index b57f670..af7de74 100644 --- a/Hyperbar.Windows/ApplicationBarViewModel.cs +++ b/Hyperbar.Windows/ApplicationBarViewModel.cs @@ -2,13 +2,13 @@ [NotificationHandler(nameof(IWidgetHostViewModel))] public partial class ApplicationBarViewModel : - ObservableCollectionViewModel, - ITemplatedViewModel + ObservableCollectionViewModel { - public ApplicationBarViewModel(ITemplateFactory templateFactory, + public ApplicationBarViewModel(IViewModelTemplateFactory templateFactory, + IServiceProvider serviceProvider, IServiceFactory serviceFactory, IMediator mediator, - IDisposer disposer) : base(serviceFactory, mediator, disposer) + IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer) { TemplateFactory = templateFactory; @@ -16,5 +16,5 @@ public partial class ApplicationBarViewModel : Add(1); } - public ITemplateFactory TemplateFactory { get; } + public IViewModelTemplateFactory TemplateFactory { get; } } \ No newline at end of file diff --git a/Hyperbar.Windows/GeneralSettingsNavigationView.xaml b/Hyperbar.Windows/GeneralSettingsNavigationView.xaml new file mode 100644 index 0000000..68d1872 --- /dev/null +++ b/Hyperbar.Windows/GeneralSettingsNavigationView.xaml @@ -0,0 +1,6 @@ + + diff --git a/Hyperbar.Windows/GeneralSettingsNavigationView.xaml.cs b/Hyperbar.Windows/GeneralSettingsNavigationView.xaml.cs new file mode 100644 index 0000000..d4fc51c --- /dev/null +++ b/Hyperbar.Windows/GeneralSettingsNavigationView.xaml.cs @@ -0,0 +1,10 @@ +using Microsoft.UI.Xaml.Controls; + +namespace Hyperbar.Windows; + +public sealed partial class GeneralSettingsNavigationView : + NavigationViewItem +{ + public GeneralSettingsNavigationView() => + InitializeComponent(); +} diff --git a/Hyperbar.Windows/GeneralSettingsNavigationViewModel.cs b/Hyperbar.Windows/GeneralSettingsNavigationViewModel.cs new file mode 100644 index 0000000..a345f95 --- /dev/null +++ b/Hyperbar.Windows/GeneralSettingsNavigationViewModel.cs @@ -0,0 +1,10 @@ +namespace Hyperbar.Windows; + +public class GeneralSettingsNavigationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IMediator mediator, + IDisposer disposer, + string text) : + NavigationViewModel(serviceProvider, serviceFactory, mediator, disposer, text) +{ +} \ No newline at end of file diff --git a/Hyperbar.Windows/Hyperbar.Windows.csproj b/Hyperbar.Windows/Hyperbar.Windows.csproj index f6d3fe6..55e427b 100644 --- a/Hyperbar.Windows/Hyperbar.Windows.csproj +++ b/Hyperbar.Windows/Hyperbar.Windows.csproj @@ -15,10 +15,12 @@ + + @@ -55,6 +57,16 @@ + + + MSBuild:Compile + + + + + MSBuild:Compile + + MSBuild:Compile diff --git a/Hyperbar.Windows/PrimaryView.xaml b/Hyperbar.Windows/PrimaryView.xaml index d0e740d..410330d 100644 --- a/Hyperbar.Windows/PrimaryView.xaml +++ b/Hyperbar.Windows/PrimaryView.xaml @@ -3,10 +3,10 @@ x:Class="Hyperbar.Windows.PrimaryView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:windows="using:Hyperbar.UI.Windows"> + xmlns:ui="using:Hyperbar.UI.Windows"> diff --git a/Hyperbar.Windows/PrimaryViewModel.cs b/Hyperbar.Windows/PrimaryViewModel.cs index e6504aa..5781f40 100644 --- a/Hyperbar.Windows/PrimaryViewModel.cs +++ b/Hyperbar.Windows/PrimaryViewModel.cs @@ -3,17 +3,17 @@ namespace Hyperbar.Widget; [NotificationHandler(nameof(IWidgetHostViewModel))] -public partial class PrimaryViewModel(ITemplateFactory templateFactory, +public partial class PrimaryViewModel(IViewModelTemplateFactory templateFactory, + IServiceProvider serviceProvider, IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, int index) : - ObservableCollectionViewModel(serviceFactory, mediator, disposer), - IWidgetHostViewModel, - ITemplatedViewModel + ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer), + IWidgetHostViewModel { [ObservableProperty] private int index = index; - public ITemplateFactory TemplateFactory => templateFactory; + public IViewModelTemplateFactory TemplateFactory => templateFactory; } \ No newline at end of file diff --git a/Hyperbar.Windows/SecondaryView.xaml b/Hyperbar.Windows/SecondaryView.xaml index 5691e1a..6b24637 100644 --- a/Hyperbar.Windows/SecondaryView.xaml +++ b/Hyperbar.Windows/SecondaryView.xaml @@ -3,9 +3,9 @@ x:Class="Hyperbar.Windows.SecondaryView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:windows="using:Hyperbar.UI.Windows"> + xmlns:ui="using:Hyperbar.UI.Windows"> - + diff --git a/Hyperbar.Windows/SecondaryViewModel.cs b/Hyperbar.Windows/SecondaryViewModel.cs index eb78c8a..e44b7b3 100644 --- a/Hyperbar.Windows/SecondaryViewModel.cs +++ b/Hyperbar.Windows/SecondaryViewModel.cs @@ -4,17 +4,17 @@ using Hyperbar.Windows; namespace Hyperbar.Widget; public partial class SecondaryViewModel : - ObservableCollectionViewModel, - ITemplatedViewModel + ObservableCollectionViewModel { [ObservableProperty] private int index; - public SecondaryViewModel(ITemplateFactory templateFactory, + public SecondaryViewModel(IViewModelTemplateFactory templateFactory, + IServiceProvider serviceProvider, IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - int index) : base(serviceFactory, mediator, disposer) + int index) : base(serviceProvider, serviceFactory, mediator, disposer) { TemplateFactory = templateFactory; this.index = index; @@ -22,5 +22,5 @@ public partial class SecondaryViewModel : Add(); } - public ITemplateFactory TemplateFactory { get; } + public IViewModelTemplateFactory TemplateFactory { get; } } \ No newline at end of file diff --git a/Hyperbar.Windows/SettingsButtonViewModel.cs b/Hyperbar.Windows/SettingsButtonViewModel.cs index d2e1ad7..02ec649 100644 --- a/Hyperbar.Windows/SettingsButtonViewModel.cs +++ b/Hyperbar.Windows/SettingsButtonViewModel.cs @@ -4,21 +4,21 @@ using CommunityToolkit.Mvvm.Input; namespace Hyperbar.Windows; public partial class SettingsButtonViewModel : - ObservableViewModel, - ITemplatedViewModel + ObservableViewModel { [ObservableProperty] private IRelayCommand? invokeCommand; - public SettingsButtonViewModel(ITemplateFactory templateFactory, + public SettingsButtonViewModel(IViewModelTemplateFactory templateFactory, + IServiceProvider serviceProvider, IServiceFactory serviceFactory, IMediator mediator, - IDisposer disposer) : base(serviceFactory, mediator, disposer) + IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer) { TemplateFactory = templateFactory; InvokeCommand = new AsyncRelayCommand(async () => await mediator.PublishAsync(new Navigate("Settings"))); } - public ITemplateFactory TemplateFactory { get; } + public IViewModelTemplateFactory TemplateFactory { get; } } diff --git a/Hyperbar.Windows/SettingsView.xaml b/Hyperbar.Windows/SettingsView.xaml index ea28db8..f81082e 100644 --- a/Hyperbar.Windows/SettingsView.xaml +++ b/Hyperbar.Windows/SettingsView.xaml @@ -3,7 +3,8 @@ x:Class="Hyperbar.Windows.SettingsView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:hyperbar="using:Hyperbar"> + xmlns:ui="using:Hyperbar.UI.Windows" + xmlns:windows="using:Hyperbar.Windows"> @@ -11,11 +12,6 @@ IsBackButtonVisible="Collapsed" IsPaneToggleButtonVisible="False" IsSettingsVisible="False" - MenuItemsSource="{x:Bind ViewModel, Mode=OneWay}"> - - - - - - + MenuItemTemplateSelector="{ui:ViewModelTemplate}" + MenuItemsSource="{x:Bind ViewModel, Mode=OneWay}" /> diff --git a/Hyperbar.Windows/SettingsView.xaml.cs b/Hyperbar.Windows/SettingsView.xaml.cs index e064723..79d499d 100644 --- a/Hyperbar.Windows/SettingsView.xaml.cs +++ b/Hyperbar.Windows/SettingsView.xaml.cs @@ -1,3 +1,5 @@ +using Hyperbar.UI.Windows; +using Microsoft.UI; using Microsoft.UI.Xaml; namespace Hyperbar.Windows; @@ -5,9 +7,18 @@ namespace Hyperbar.Windows; public partial class SettingsView : Window { - public SettingsView() => + public SettingsView() + { InitializeComponent(); + this.TitleBarConfiguration(args => + { + args.ExtendsContentIntoTitleBar = true; + args.ButtonBackgroundColor = Colors.Transparent; + args.ButtonInactiveBackgroundColor = Colors.Transparent; + }); + } + protected SettingsViewModel ViewModel => (SettingsViewModel)(Content as FrameworkElement)!.DataContext; } diff --git a/Hyperbar.Windows/SettingsViewModel.cs b/Hyperbar.Windows/SettingsViewModel.cs index 393523b..e1927cf 100644 --- a/Hyperbar.Windows/SettingsViewModel.cs +++ b/Hyperbar.Windows/SettingsViewModel.cs @@ -1,13 +1,19 @@ namespace Hyperbar.Windows; public partial class SettingsViewModel : - ObservableCollectionViewModel + ObservableCollectionViewModel { - public SettingsViewModel(IServiceFactory serviceFactory, + public SettingsViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, - IDisposer disposer) : base(serviceFactory, mediator, disposer) + IDisposer disposer, + IViewModelTemplateFactory templateFactory) : base(serviceProvider, serviceFactory, mediator, disposer) { - Add("General"); - Add("Widgets"); + Add("General"); + Add("Widgets"); + + TemplateFactory = templateFactory; } + + public IViewModelTemplateFactory TemplateFactory { get; } } diff --git a/Hyperbar.Windows/WidgetNavigationViewModel.cs b/Hyperbar.Windows/WidgetNavigationViewModel.cs new file mode 100644 index 0000000..863ecbe --- /dev/null +++ b/Hyperbar.Windows/WidgetNavigationViewModel.cs @@ -0,0 +1,10 @@ +namespace Hyperbar.Windows; + +public class WidgetNavigationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IMediator mediator, + IDisposer disposer, + string text) : + NavigationViewModel(serviceProvider, serviceFactory, mediator, disposer, text) +{ +} diff --git a/Hyperbar.Windows/WidgetSettingsNavigationView.xaml b/Hyperbar.Windows/WidgetSettingsNavigationView.xaml new file mode 100644 index 0000000..404d0e0 --- /dev/null +++ b/Hyperbar.Windows/WidgetSettingsNavigationView.xaml @@ -0,0 +1,6 @@ + + diff --git a/Hyperbar.Windows/WidgetSettingsNavigationView.xaml.cs b/Hyperbar.Windows/WidgetSettingsNavigationView.xaml.cs new file mode 100644 index 0000000..3573a21 --- /dev/null +++ b/Hyperbar.Windows/WidgetSettingsNavigationView.xaml.cs @@ -0,0 +1,10 @@ +using Microsoft.UI.Xaml.Controls; + +namespace Hyperbar.Windows; + +public sealed partial class WidgetSettingsNavigationView : + NavigationViewItem +{ + public WidgetSettingsNavigationView() => + InitializeComponent(); +} diff --git a/Hyperbar.Windows/WidgetSettingsNavigationViewModel.cs b/Hyperbar.Windows/WidgetSettingsNavigationViewModel.cs new file mode 100644 index 0000000..5e7a297 --- /dev/null +++ b/Hyperbar.Windows/WidgetSettingsNavigationViewModel.cs @@ -0,0 +1,11 @@ +namespace Hyperbar.Windows; + +public class WidgetSettingsNavigationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IMediator mediator, + IDisposer disposer, + string text) : + NavigationViewModel(serviceProvider, serviceFactory, mediator, disposer, text) +{ + +} diff --git a/Hyperbar/Extensions/IServiceCollectionExtensions.cs b/Hyperbar/Extensions/IServiceCollectionExtensions.cs index 8841216..df71c07 100644 --- a/Hyperbar/Extensions/IServiceCollectionExtensions.cs +++ b/Hyperbar/Extensions/IServiceCollectionExtensions.cs @@ -164,9 +164,9 @@ public static class IServiceCollectionExtensions services.AddKeyedTransient(contentType, key); services.AddKeyedTransient(templateType, key); - services.AddTransient(provider => new ContentTemplateDescriptor + services.AddTransient(provider => new ViewModelTemplateDescriptor { - ContentType = contentType, + ViewModelType = contentType, TemplateType = templateType, Key = key }); diff --git a/Hyperbar/Lifecycles/INavigationViewModel.cs b/Hyperbar/Lifecycles/INavigationViewModel.cs new file mode 100644 index 0000000..8377c00 --- /dev/null +++ b/Hyperbar/Lifecycles/INavigationViewModel.cs @@ -0,0 +1,7 @@ +namespace Hyperbar; + +public interface INavigationViewModel : + IObservableViewModel +{ + string Text { get; set; } +} diff --git a/Hyperbar/Lifecycles/IObservableViewModel.cs b/Hyperbar/Lifecycles/IObservableViewModel.cs index f9f6e35..87eb6bf 100644 --- a/Hyperbar/Lifecycles/IObservableViewModel.cs +++ b/Hyperbar/Lifecycles/IObservableViewModel.cs @@ -1,8 +1,14 @@ -using System.Windows.Input; +namespace Hyperbar; -namespace Hyperbar; - -public interface IObservableViewModel +public interface IObservableViewModel : + IInitialization, + IDisposable { - ICommand InitializeCommand { get; } + public IDisposer Disposer { get; } + + public IMediator Mediator { get; } + + public IServiceFactory ServiceFactory { get; } + + public IServiceProvider ServiceProvider { get; } } \ No newline at end of file diff --git a/Hyperbar/Lifecycles/NavigateHandler.cs b/Hyperbar/Lifecycles/NavigateHandler.cs index 9732260..d89e049 100644 --- a/Hyperbar/Lifecycles/NavigateHandler.cs +++ b/Hyperbar/Lifecycles/NavigateHandler.cs @@ -5,7 +5,7 @@ namespace Hyperbar; public class NavigateHandler : INotificationHandler { - private readonly IEnumerable contentTemplateDescriptors; + private readonly IEnumerable contentTemplateDescriptors; private readonly IServiceProvider provider; private readonly IMediator mediator; private readonly IEnumerable navigationDescriptors; @@ -13,7 +13,7 @@ public class NavigateHandler : public NavigateHandler(IServiceProvider provider, IMediator mediator, IEnumerable navigationDescriptors, - IEnumerable contentTemplateDescriptors) + IEnumerable contentTemplateDescriptors) { this.provider = provider; this.mediator = mediator; @@ -25,7 +25,7 @@ public class NavigateHandler : CancellationToken cancellationToken) { if (contentTemplateDescriptors.FirstOrDefault(x => x.Key == args.Key) - is IContentTemplateDescriptor contentTemplateDescriptor) + is IViewModelTemplateDescriptor contentTemplateDescriptor) { if (navigationDescriptors.FirstOrDefault(x => contentTemplateDescriptor.TemplateType == x.Type || contentTemplateDescriptor.TemplateType.BaseType == x.Type) is { } navigationDescriptor) @@ -35,7 +35,7 @@ public class NavigateHandler : { if (provider.GetRequiredKeyedService(contentTemplateDescriptor.TemplateType, contentTemplateDescriptor.Key) is { } template && - provider.GetRequiredKeyedService(contentTemplateDescriptor.ContentType, + provider.GetRequiredKeyedService(contentTemplateDescriptor.ViewModelType, contentTemplateDescriptor.Key) is { } content) { Type navigateType = typeof(Navigate<>) diff --git a/Hyperbar/Lifecycles/NavigationViewModel.cs b/Hyperbar/Lifecycles/NavigationViewModel.cs index 415fc79..1f70282 100644 --- a/Hyperbar/Lifecycles/NavigationViewModel.cs +++ b/Hyperbar/Lifecycles/NavigationViewModel.cs @@ -3,16 +3,32 @@ namespace Hyperbar; public partial class NavigationViewModel : - ObservableCollectionViewModel + ObservableCollectionViewModel, + INavigationViewModel { [ObservableProperty] private string? text; - public NavigationViewModel(IServiceFactory serviceFactory, + public NavigationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - string text) : base(serviceFactory, mediator, disposer) + string text) : base(serviceProvider, serviceFactory, mediator, disposer) { this.text = text; } } + +public partial class NavigationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IMediator mediator, + IDisposer disposer, + string text) : + ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer), + INavigationViewModel + where TNavigationViewModel : + INavigationViewModel +{ + [ObservableProperty] + private string? text = text; +} diff --git a/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs b/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs index fbfd83f..cd0f29f 100644 --- a/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs +++ b/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs @@ -8,31 +8,29 @@ using System.Windows.Input; namespace Hyperbar; -public partial class ObservableCollectionViewModel : +public partial class ObservableCollectionViewModel : ObservableObject, - IObservableCollectionViewModel, - IList, + IObservableCollectionViewModel, + IList, IList, - IReadOnlyList, + IReadOnlyList, INotifyCollectionChanged, - INotificationHandler>, - INotificationHandler>, - INotificationHandler>, - INotificationHandler>, - INotificationHandler>, - IDisposable, - IInitialization - where TItem : - IDisposable + INotificationHandler>, + INotificationHandler>, + INotificationHandler>, + INotificationHandler>, + INotificationHandler> { - private readonly ObservableCollection collection = []; + private readonly ObservableCollection collection = []; private bool isInitialized; - public ObservableCollectionViewModel(IServiceFactory serviceFactory, + public ObservableCollectionViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer) { + ServiceProvider = serviceProvider; ServiceFactory = serviceFactory; Mediator = mediator; Disposer = disposer; @@ -42,11 +40,13 @@ public partial class ObservableCollectionViewModel : collection.CollectionChanged += OnCollectionChanged; } - public ObservableCollectionViewModel(IServiceFactory serviceFactory, + public ObservableCollectionViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer, - IEnumerable items) + IEnumerable items) { + ServiceProvider = serviceProvider; ServiceFactory = serviceFactory; Mediator = mediator; Disposer = disposer; @@ -61,28 +61,28 @@ public partial class ObservableCollectionViewModel : public int Count => collection.Count; + public IDisposer Disposer { get; private set; } + public ICommand InitializeCommand => - new AsyncRelayCommand(CoreInitializeAsync); + new AsyncRelayCommand(CoreInitializeAsync); bool IList.IsFixedSize => false; - bool ICollection.IsReadOnly => false; + bool ICollection.IsReadOnly => false; bool IList.IsReadOnly => false; bool ICollection.IsSynchronized => false; + public IMediator Mediator { get; private set; } + + public IServiceFactory ServiceFactory { get; private set; } + object ICollection.SyncRoot => this; - protected IDisposer Disposer { get; private set; } + public IServiceProvider ServiceProvider { get; private set; } - protected IList Items => collection; - - protected IMediator Mediator { get; private set; } - - protected IServiceFactory ServiceFactory { get; private set; } - - public TItem this[int index] + public TViewModel this[int index] { get => collection[index]; set => SetItem(index, value); @@ -93,11 +93,11 @@ public partial class ObservableCollectionViewModel : get => collection[index]; set { - TItem? item = default; + TViewModel? item = default; try { - item = (TItem)value!; + item = (TViewModel)value!; } catch (InvalidCastException) { @@ -108,16 +108,16 @@ public partial class ObservableCollectionViewModel : } } - public TItem Add() + public TViewModel Add() { - TItem? item = ServiceFactory.Create(); + TViewModel? item = ServiceFactory.Create(); Add(item); return item; } - public TItem Add(params object?[] parameters) - where T : TItem + public TViewModel Add(params object?[] parameters) + where T : TViewModel { T? item = ServiceFactory.Create(parameters); Add(item); @@ -125,9 +125,9 @@ public partial class ObservableCollectionViewModel : return item; } - public TItem Add() + public TViewModel Add() where T : - TItem + TViewModel { T? item = ServiceFactory.Create(); Add(item); @@ -135,7 +135,7 @@ public partial class ObservableCollectionViewModel : return item; } - public void Add(TItem item) + public void Add(TViewModel item) { int index = collection.Count; InsertItem(index, item); @@ -144,16 +144,16 @@ public partial class ObservableCollectionViewModel : public void Add(object item) { int index = collection.Count; - InsertItem(index, (TItem)item); + InsertItem(index, (TViewModel)item); } int IList.Add(object? value) { - TItem? item = default; + TViewModel? item = default; try { - item = (TItem)value!; + item = (TViewModel)value!; } catch (InvalidCastException) { @@ -164,9 +164,9 @@ public partial class ObservableCollectionViewModel : return Count - 1; } - public void AddRange(IEnumerable items) + public void AddRange(IEnumerable items) { - foreach (TItem? item in items) + foreach (TViewModel? item in items) { Add(item); } @@ -174,7 +174,7 @@ public partial class ObservableCollectionViewModel : public void Clear() { - foreach (TItem item in collection) + foreach (TViewModel item in collection) { Disposer.Dispose(item); } @@ -182,17 +182,17 @@ public partial class ObservableCollectionViewModel : ClearItems(); } - public bool Contains(TItem item) => + public bool Contains(TViewModel item) => collection.Contains(item); bool IList.Contains(object? value) => - IsCompatibleObject(value) && Contains((TItem)value!); + IsCompatibleObject(value) && Contains((TViewModel)value!); - public void CopyTo(TItem[] array, int index) => + public void CopyTo(TViewModel[] array, int index) => collection.CopyTo(array, index); void ICollection.CopyTo(Array array, int index) => - collection.CopyTo((TItem[])array, index); + collection.CopyTo((TViewModel[])array, index); public virtual void Dispose() { @@ -200,16 +200,16 @@ public partial class ObservableCollectionViewModel : Disposer.Dispose(this); } - public System.Collections.Generic.IEnumerator GetEnumerator() => + public System.Collections.Generic.IEnumerator GetEnumerator() => collection.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)collection).GetEnumerator(); - public Task Handle(Remove notification, + public Task Handle(Remove notification, CancellationToken cancellationToken) { - foreach (TItem item in this.ToList()) + foreach (TViewModel item in this.ToList()) { if (notification.Value is not null && notification.Value.Equals(item)) { @@ -220,10 +220,10 @@ public partial class ObservableCollectionViewModel : return Task.CompletedTask; } - public Task Handle(Create notification, + public Task Handle(Create notification, CancellationToken cancellationToken) { - if (notification.Value is TItem item) + if (notification.Value is TViewModel item) { Add(item); } @@ -231,10 +231,10 @@ public partial class ObservableCollectionViewModel : return Task.CompletedTask; } - public Task Handle(Insert notification, + public Task Handle(Insert notification, CancellationToken cancellationToken) { - if (notification.Value is TItem item) + if (notification.Value is TViewModel item) { Insert(notification.Index, item); } @@ -242,10 +242,10 @@ public partial class ObservableCollectionViewModel : return Task.CompletedTask; } - public Task Handle(Move notification, + public Task Handle(Move notification, CancellationToken cancellationToken) { - if (notification.Value is TItem item) + if (notification.Value is TViewModel item) { Move(notification.Index, item); } @@ -253,10 +253,10 @@ public partial class ObservableCollectionViewModel : return Task.CompletedTask; } - public Task Handle(Replace notification, + public Task Handle(Replace notification, CancellationToken cancellationToken) { - if (notification.Value is TItem item) + if (notification.Value is TViewModel item) { Replace(notification.Index, item); } @@ -264,25 +264,27 @@ public partial class ObservableCollectionViewModel : return Task.CompletedTask; } - public int IndexOf(TItem item) => + public int IndexOf(TViewModel item) => collection.IndexOf(item); int IList.IndexOf(object? value) => IsCompatibleObject(value) ? - IndexOf((TItem)value!) : -1; - public void Insert(int index, TItem item) => - InsertItem(index, item); + IndexOf((TViewModel)value!) : -1; + public virtual Task InitializeAsync() => Task.CompletedTask; + + public void Insert(int index, TViewModel item) => + InsertItem(index, item); void IList.Insert(int index, object? value) { - if (value is TItem item) + if (value is TViewModel item) { Insert(index, item); } } - public bool Move(int index, TItem item) + public bool Move(int index, TViewModel item) { int oldIndex = collection.IndexOf(item); if (oldIndex < 0) @@ -295,13 +297,7 @@ public partial class ObservableCollectionViewModel : return true; } - - public virtual Task InitializeAsync() - { - return Task.CompletedTask; - } - - public bool Remove(TItem item) + public bool Remove(TViewModel item) { int index = collection.IndexOf(item); if (index < 0) @@ -319,14 +315,14 @@ public partial class ObservableCollectionViewModel : { if (IsCompatibleObject(value)) { - Remove((TItem)value!); + Remove((TViewModel)value!); } } public void RemoveAt(int index) => RemoveItem(index); - public bool Replace(int index, TItem item) + public bool Replace(int index, TViewModel item) { if (index <= Count - 1) { @@ -346,7 +342,7 @@ public partial class ObservableCollectionViewModel : collection.Clear(); protected virtual void InsertItem(int index, - TItem value) + TViewModel value) { Disposer.Add(this, value); Disposer.Add(value, value, Disposable.Create(() => @@ -363,11 +359,11 @@ public partial class ObservableCollectionViewModel : protected virtual void RemoveItem(int index) => collection.RemoveAt(index); - protected virtual void SetItem(int index, TItem item) => + protected virtual void SetItem(int index, TViewModel item) => collection[index] = item; private static bool IsCompatibleObject(object? value) => - (value is TItem) || (value == null && default(TItem) == null); + (value is TViewModel) || (value == null && default(TViewModel) == null); private async Task CoreInitializeAsync() { @@ -378,7 +374,7 @@ public partial class ObservableCollectionViewModel : isInitialized = true; - await Mediator.PublishAsync>(); + await Mediator.PublishAsync>(); await InitializeAsync(); } @@ -386,7 +382,8 @@ public partial class ObservableCollectionViewModel : CollectionChanged?.Invoke(this, args); } -public class ObservableCollectionViewModel(IServiceFactory serviceFactory, +public class ObservableCollectionViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer) : - ObservableCollectionViewModel(serviceFactory, mediator, disposer); \ No newline at end of file + ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer); \ No newline at end of file diff --git a/Hyperbar/Lifecycles/ObservableViewModel.cs b/Hyperbar/Lifecycles/ObservableViewModel.cs index eba77dd..307340d 100644 --- a/Hyperbar/Lifecycles/ObservableViewModel.cs +++ b/Hyperbar/Lifecycles/ObservableViewModel.cs @@ -1,16 +1,45 @@ using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using System.Windows.Input; namespace Hyperbar; -public class ObservableViewModel(IServiceFactory serviceFactory, +public class ObservableViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, IMediator mediator, IDisposer disposer) : ObservableObject, - IDisposable + IObservableViewModel { - public IServiceFactory ServiceFactory => serviceFactory; + private bool isInitialized; + + public IDisposer Disposer => disposer; + + public ICommand InitializeCommand => + new AsyncRelayCommand(CoreInitializeAsync); public IMediator Mediator => mediator; - public void Dispose() => disposer.Dispose(this); + public IServiceFactory ServiceFactory => serviceFactory; + + public IServiceProvider ServiceProvider => serviceProvider; + + public void Dispose() + { + GC.SuppressFinalize(this); + disposer.Dispose(this); + } + + public virtual Task InitializeAsync() => Task.CompletedTask; + + private async Task CoreInitializeAsync() + { + if (isInitialized) + { + return; + } + + isInitialized = true; + await InitializeAsync(); + } } diff --git a/Hyperbar/Templates/ContentTemplateDescriptor.cs b/Hyperbar/Templates/ContentTemplateDescriptor.cs deleted file mode 100644 index eed118d..0000000 --- a/Hyperbar/Templates/ContentTemplateDescriptor.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Hyperbar; - -public record ContentTemplateDescriptor : - IContentTemplateDescriptor -{ - public required Type ContentType { get; set; } - - public required Type TemplateType { get; set; } - - public required object Key { get; set; } -} \ No newline at end of file diff --git a/Hyperbar/Templates/ITemplatedViewModel.cs b/Hyperbar/Templates/ITemplatedViewModel.cs deleted file mode 100644 index 9dbb8cd..0000000 --- a/Hyperbar/Templates/ITemplatedViewModel.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Hyperbar; - -public interface ITemplatedViewModel -{ - ITemplateFactory TemplateFactory { get; } -} \ No newline at end of file diff --git a/Hyperbar/Templates/IContentTemplateDescriptor.cs b/Hyperbar/Templates/IViewModelTemplateDescriptor.cs similarity index 53% rename from Hyperbar/Templates/IContentTemplateDescriptor.cs rename to Hyperbar/Templates/IViewModelTemplateDescriptor.cs index 8b6b56f..3492d61 100644 --- a/Hyperbar/Templates/IContentTemplateDescriptor.cs +++ b/Hyperbar/Templates/IViewModelTemplateDescriptor.cs @@ -1,10 +1,10 @@ namespace Hyperbar; -public interface IContentTemplateDescriptor +public interface IViewModelTemplateDescriptor { - Type ContentType { get; set; } - object Key { get; set; } Type TemplateType { get; set; } + + Type ViewModelType { get; set; } } \ No newline at end of file diff --git a/Hyperbar/Templates/IViewModelTemplateDescriptorProvider.cs b/Hyperbar/Templates/IViewModelTemplateDescriptorProvider.cs new file mode 100644 index 0000000..e29d180 --- /dev/null +++ b/Hyperbar/Templates/IViewModelTemplateDescriptorProvider.cs @@ -0,0 +1,6 @@ +namespace Hyperbar; + +public interface IViewModelTemplateDescriptorProvider +{ + IViewModelTemplateDescriptor? Get(object key); +} diff --git a/Hyperbar/Lifecycles/ITemplateFactory.cs b/Hyperbar/Templates/IViewModelTemplateFactory.cs similarity index 57% rename from Hyperbar/Lifecycles/ITemplateFactory.cs rename to Hyperbar/Templates/IViewModelTemplateFactory.cs index 7ab6c1a..d46f917 100644 --- a/Hyperbar/Lifecycles/ITemplateFactory.cs +++ b/Hyperbar/Templates/IViewModelTemplateFactory.cs @@ -1,6 +1,6 @@ namespace Hyperbar; -public interface ITemplateFactory +public interface IViewModelTemplateFactory { object? Create(object key); } \ No newline at end of file diff --git a/Hyperbar/Templates/ViewModelTemplateDescriptor.cs b/Hyperbar/Templates/ViewModelTemplateDescriptor.cs new file mode 100644 index 0000000..291fd03 --- /dev/null +++ b/Hyperbar/Templates/ViewModelTemplateDescriptor.cs @@ -0,0 +1,11 @@ +namespace Hyperbar; + +public record ViewModelTemplateDescriptor : + IViewModelTemplateDescriptor +{ + public required Type ViewModelType { get; set; } + + public required Type TemplateType { get; set; } + + public required object Key { get; set; } +} \ No newline at end of file diff --git a/Hyperbar/Templates/ViewModelTemplateDescriptorProvider.cs b/Hyperbar/Templates/ViewModelTemplateDescriptorProvider.cs new file mode 100644 index 0000000..f80fc22 --- /dev/null +++ b/Hyperbar/Templates/ViewModelTemplateDescriptorProvider.cs @@ -0,0 +1,16 @@ +namespace Hyperbar; + +public class ViewModelTemplateDescriptorProvider(IEnumerable descriptors) : + IViewModelTemplateDescriptorProvider +{ + public IViewModelTemplateDescriptor? Get(object key) + { + if (descriptors.FirstOrDefault(x => x.Key == key) + is IViewModelTemplateDescriptor descriptor) + { + return descriptor; + } + + return default; + } +} diff --git a/Hyperbar/Templates/ViewModelTemplateFactory.cs b/Hyperbar/Templates/ViewModelTemplateFactory.cs new file mode 100644 index 0000000..e2bf4e4 --- /dev/null +++ b/Hyperbar/Templates/ViewModelTemplateFactory.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Hyperbar; + +public class ViewModelTemplateFactory(IViewModelTemplateDescriptorProvider descriptors, + IServiceProvider services) : + IViewModelTemplateFactory +{ + public object? Create(object key) + { + if (descriptors.Get(key) + is IViewModelTemplateDescriptor descriptor) + { + if (services.GetRequiredKeyedService(descriptor.TemplateType, + descriptor.Key) is { } template) + { + return template; + } + } + + return default; + } +} \ No newline at end of file