Get ContentControl navigation working

This commit is contained in:
TheXamlGuy
2024-02-11 18:09:22 +00:00
parent 565c6866d8
commit 812556f8b0
133 changed files with 335 additions and 195 deletions
@@ -0,0 +1,9 @@
using Microsoft.UI.Xaml;
namespace Hyperbar.UI.Windows;
public interface IViewModelContentBinder
{
void Bind(FrameworkElement view,
object context);
}
@@ -1,6 +0,0 @@
namespace Hyperbar.UI.Windows;
public interface IViewModelTemplate
{
}
@@ -0,0 +1,6 @@
namespace Hyperbar.UI.Windows;
public interface IViewModelTemplateSelector
{
}
+16 -6
View File
@@ -7,15 +7,25 @@ public sealed class NavigateAction :
DependencyObject,
IAction
{
public static readonly DependencyProperty PathProperty =
DependencyProperty.Register(nameof(Path),
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register(nameof(Name),
typeof(string), typeof(NavigateAction),
new PropertyMetadata(null));
public string Path
public static readonly DependencyProperty TargetNameProperty =
DependencyProperty.Register(nameof(Name),
typeof(string), typeof(NavigateAction),
new PropertyMetadata(null));
public string Name
{
get => (string)GetValue(PathProperty);
set => SetValue(PathProperty, value);
get => (string)GetValue(NameProperty);
set => SetValue(NameProperty, value);
}
public string TargetName
{
get => (string)GetValue(TargetNameProperty);
set => SetValue(TargetNameProperty, value);
}
public object Execute(object sender, object parameter)
@@ -24,7 +34,7 @@ public sealed class NavigateAction :
{
if (frameworkElement.DataContext is IObservableViewModel observableViewModel)
{
observableViewModel.Publisher.PublishAsync(new Navigate(Path))
observableViewModel.Publisher.PublishAsync(new Navigate(Name, TargetName ?? null))
.GetAwaiter().GetResult();
}
}
@@ -0,0 +1,31 @@
using Microsoft.UI.Xaml;
using System.Reflection;
namespace Hyperbar.UI.Windows;
public class ViewModelContentBinder(NavigationTargetCollection contents) :
IViewModelContentBinder
{
public void Bind(FrameworkElement view,
object context)
{
if (context.GetType().GetCustomAttributes<NavigationTargetAttribute>()
is IEnumerable<NavigationTargetAttribute> attributes)
{
foreach (NavigationTargetAttribute attribute in attributes)
{
if (view.FindName(attribute.Name) is FrameworkElement content)
{
contents.Add(attribute.Name, content);
void HandleUnloaded(object sender, RoutedEventArgs args)
{
view.Unloaded -= HandleUnloaded;
contents.Remove(attribute.Name);
}
view.Unloaded += HandleUnloaded;
}
}
}
}
}
@@ -4,22 +4,13 @@ using Microsoft.UI.Xaml.Markup;
namespace Hyperbar.UI.Windows;
public class ViewModelBinder
{
public void Bind(object viewModel,
FrameworkElement view)
{
view.DataContext ??= viewModel;
}
}
public class ViewModelTemplate(IViewModelTemplateDescriptorProvider descriptors) :
public class ViewModelTemplateSelector(IViewModelTemplateProvider descriptors) :
DataTemplateSelector,
IViewModelTemplate
IViewModelTemplateSelector
{
protected override DataTemplate SelectTemplateCore(object item)
{
return descriptors.Get(item.GetType().Name) is IViewModelTemplateDescriptor descriptor
return descriptors.Get(item.GetType().Name) is Hyperbar.IViewModelTemplate descriptor
? CreateDataTemplate(descriptor)
: new DataTemplate();
}
@@ -28,7 +19,7 @@ public class ViewModelTemplate(IViewModelTemplateDescriptorProvider descriptors)
DependencyObject container) =>
SelectTemplateCore(item);
private static DataTemplate CreateDataTemplate(IViewModelTemplateDescriptor descriptor)
private static DataTemplate CreateDataTemplate(Hyperbar.IViewModelTemplate descriptor)
{
string xamlString = @$"
<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
+12 -7
View File
@@ -3,24 +3,28 @@ using Microsoft.UI.Xaml.Controls;
namespace Hyperbar.UI.Windows;
public class FrameHandler :
INavigationHandler<Frame>
public class ContentControlHandler(IViewModelContentBinder viewModelContentBinder) :
INavigationHandler<ContentControl>
{
public Task Handle(Navigate<Frame> args,
CancellationToken cancellationToken = default)
public Task Handle(Navigate<ContentControl> args,
CancellationToken cancellationToken)
{
if (args.Target is ContentControl contentControl)
{
contentControl.Content = args.View;
}
return Task.CompletedTask;
}
}
public class WindowHandler :
public class WindowHandler(IViewModelContentBinder viewModelContentBinder) :
INavigationHandler<Window>
{
public Task Handle(Navigate<Window> args,
CancellationToken cancellationToken)
{
if (args.View is Window window)
if (args.Target is Window window)
{
if (window.Content is FrameworkElement content)
{
@@ -33,8 +37,9 @@ public class WindowHandler :
}
}
//ViewModelBinder.Bind(args.ViewModel, content);
viewModelContentBinder.Bind(content, window);
window.Closed += HandleClosed;
content.DataContext = args.ViewModel;
}
window.Activate();
@@ -2,12 +2,11 @@
<UserControl
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:ui="using:Hyperbar.UI.Windows">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ItemsControl
HorizontalAlignment="Right"
HorizontalContentAlignment="Right"
ItemTemplateSelector="{Binding Template}"
ItemTemplateSelector="{Binding ViewModelTemplateSelector}"
ItemsSource="{x:Bind ViewModel}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
@@ -7,14 +7,14 @@ namespace Hyperbar.Widget.MediaController.Windows;
public class MediaControllerViewModel :
ObservableCollectionViewModel<WidgetComponentViewModel>
{
public MediaControllerViewModel(IViewModelTemplate template,
public MediaControllerViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
{
Template = template;
viewModelTemplateSelector = viewModelTemplateSelector;
Add<MediaInformationViewModel>();
@@ -28,5 +28,5 @@ public class MediaControllerViewModel :
await publisher.PublishAsync<Request<MediaNext>>()));
}
public IViewModelTemplate Template { get; }
public IViewModelTemplateSelector ViewModelTemplateSelector { get; }
}
@@ -5,6 +5,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<FlipView
Width="360"
ItemTemplateSelector="{Binding Template}"
ItemTemplateSelector="{Binding ViewModelTemplateSelector}"
ItemsSource="{Binding}" />
</UserControl>
@@ -2,7 +2,7 @@
namespace Hyperbar.Widget.MediaController.Windows;
public class MediaControllerWidgetViewModel(IViewModelTemplate template,
public class MediaControllerWidgetViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
@@ -12,5 +12,5 @@ public class MediaControllerWidgetViewModel(IViewModelTemplate template,
ObservableCollectionViewModel<MediaControllerViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer, items),
IWidgetViewModel
{
public IViewModelTemplate Template => template;
public IViewModelTemplateSelector ViewModelTemplateSelector => viewModelTemplateSelector;
}
@@ -12,14 +12,14 @@ public static class IServiceCollectionExtensions
// We need to feed information to the Widgets about our Windows host,
// so the Windows host can make discussions how to display and interact with the widgets.
services.AddTransient<IProxyServiceCollection<IWidgetBuilder>>(provider =>
services.AddTransient((Func<IServiceProvider, IProxyServiceCollection<IWidgetBuilder>>)(provider =>
new ProxyServiceCollection<IWidgetBuilder>(services =>
{
services.AddSingleton(provider.GetRequiredService<IList<IXamlMetadataProvider>>());
services.AddSingleton(provider.GetRequiredService<IDispatcher>());
services.AddTransient<IViewModelTemplate, ViewModelTemplate>();
services.AddTransient<IViewModelTemplateDescriptorProvider, ViewModelTemplateDescriptorProvider>();
services.AddTransient<IViewModelTemplateSelector, UI.Windows.ViewModelTemplateSelector>();
services.AddTransient<IViewModelTemplateProvider, ViewModelTemplateProvider>();
services.AddScoped<IVirtualKeyboard, VirtualKeyboard>();
services.AddHandler<KeyAcceleratorHandler>();
@@ -33,7 +33,7 @@ public static class IServiceCollectionExtensions
services.AddContentTemplate<WidgetButtonViewModel, WidgetButtonView>();
services.AddContentTemplate<WidgetSplitButtonViewModel, WidgetSplitButtonView>();
}));
})));
return services;
}
+2 -3
View File
@@ -4,10 +4,9 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:ui="using:Hyperbar.UI.Windows">
xmlns:interactivity="using:Microsoft.Xaml.Interactivity">
<Grid>
<ItemsControl ItemTemplateSelector="{Binding Template}" ItemsSource="{Binding Mode=TwoWay}">
<ItemsControl ItemTemplateSelector="{Binding ViewModelTemplateSelector}" ItemsSource="{Binding Mode=TwoWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="8" />
@@ -33,7 +33,7 @@ public static class IServiceCollectionExtensions
services.AddKeyedTransient(typeof(IWidgetViewModel), key, contentType);
services.TryAddKeyedTransient(key, (provider, key) => provider.GetService<IWidgetView>()!);
services.AddTransient<IViewModelTemplateDescriptor>(provider => new ViewModelTemplateDescriptor { ViewModelType = contentType, TemplateType = templateType, Key = key });
services.AddTransient<IViewModelTemplate>(provider => new ViewModelTemplate { 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<IViewModelTemplateDescriptor>(provider =>
new ViewModelTemplateDescriptor { ViewModelType = contentType,
services.AddTransient<IViewModelTemplate>(provider =>
new ViewModelTemplate { ViewModelType = contentType,
TemplateType = templateType, Key = key });
return services;
+8
View File
@@ -29,8 +29,16 @@ public class WidgetBuilder :
services.AddScoped<IServiceFactory>(provider =>
new ServiceFactory((type, parameters) =>
ActivatorUtilities.CreateInstance(provider, type, parameters!)));
services.AddSingleton<SubscriptionCollection>();
services.AddSingleton<ISubscriptionManager, SubscriptionManager>();
services.AddTransient<ISubscriber, Subscriber>();
services.AddTransient<IPublisher, Publisher>();
services.AddScoped<IMediator, Mediator>();
services.AddScoped<IDisposer, Disposer>();
services.AddHandler<WidgetAvailabilityChangedHandler>();
services.AddValueChangedNotification<WidgetConfiguration,
WidgetAvailability>((config) => (args) =>
+12 -5
View File
@@ -21,7 +21,7 @@ public partial class App :
base.OnLaunched(args);
IHost? host = new HostBuilder()
.UseContentRoot(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
.UseContentRoot(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
Assembly.GetEntryAssembly()?.GetName().Name!), true)
.ConfigureAppConfiguration(config =>
{
@@ -36,18 +36,24 @@ public partial class App :
services.AddHostedService<AppService>();
services.AddSingleton<IDispatcher>(new Dispatcher(DispatcherQueue.GetForCurrentThread()));
services.AddSingleton((IDispatcher)new Dispatcher(DispatcherQueue.GetForCurrentThread()));
services.AddTransient<IViewModelTemplate, ViewModelTemplate>();
services.AddTransient<IViewModelTemplateDescriptorProvider, ViewModelTemplateDescriptorProvider>();
services.AddTransient<INavigationProvider, NavigationProvider>();
services.AddSingleton<NavigationTargetCollection>();
services.AddTransient<INavigationTargetProvider, NavigationTargetProvider>();
services.AddTransient<IViewModelContentBinder, ViewModelContentBinder>();
services.AddTransient<IViewModelTemplateSelector, ViewModelTemplateSelector>();
services.AddTransient<IViewModelTemplateProvider, ViewModelTemplateProvider>();
services.AddHandler<AppConfigurationChangedHandler>();
services.AddConfiguration<AppConfiguration>(args =>
services.AddConfiguration((AppConfiguration args) =>
{
args.Placement = DesktopApplicationBarPlacemenet.Top;
});
services.AddNavigationHandler<WindowHandler>();
services.AddNavigationHandler<ContentControlHandler>();
services.AddSingleton<DesktopApplicationBar>();
services.AddContentTemplate<ApplicationBarViewModel, ApplicationBarView>();
@@ -59,6 +65,7 @@ public partial class App :
services.AddContentTemplate<GeneralSettingsNavigationViewModel, GeneralSettingsNavigationView>();
services.AddContentTemplate<WidgetSettingsNavigationViewModel, WidgetSettingsNavigationView>();
services.AddContentTemplate<WidgetSettingsViewModel, WidgetSettingsView>("WidgetSettings");
services.AddTransient<IInitializer, AppInitializer>();
})
+1 -1
View File
@@ -17,7 +17,7 @@
</UserControl.Resources>
<ItemsControl
Margin="6,0,6,0"
ItemTemplateSelector="{Binding Template}"
ItemTemplateSelector="{Binding ViewModelTemplateSelector}"
ItemsSource="{x:Bind ViewModel, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
+3 -3
View File
@@ -7,18 +7,18 @@ namespace Hyperbar.Widget;
public partial class ApplicationBarViewModel :
ObservableCollectionViewModel<IDisposable>
{
public ApplicationBarViewModel(IViewModelTemplate template,
public ApplicationBarViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
{
Template = template;
ViewModelTemplateSelector = viewModelTemplateSelector;
Add<PrimaryViewModel>(0);
Add<SecondaryViewModel>(1);
}
public IViewModelTemplate Template { get; }
public IViewModelTemplateSelector ViewModelTemplateSelector { get; }
}
@@ -6,6 +6,4 @@ public class GeneralSettingsNavigationViewModel(IServiceProvider serviceProvider
ISubscriber subscriber,
IDisposer disposer,
string text) :
NavigationViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, text)
{
}
NavigationViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, text);
+6
View File
@@ -21,6 +21,7 @@
<None Remove="SettingsButtonView.xaml" />
<None Remove="SettingsView.xaml" />
<None Remove="WidgetSettingsNavigationView.xaml" />
<None Remove="WidgetSettingsView.xaml" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\SplashScreen.scale-200.png" />
@@ -57,6 +58,11 @@
<ProjectReference Include="..\Hyperbar.Widget\Hyperbar.Widget.csproj" />
<ProjectReference Include="..\Hyperbar\Hyperbar.csproj" />
</ItemGroup>
<ItemGroup>
<Page Update="WidgetSettingsView.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="GeneralSettingsNavigationView.xaml">
<Generator>MSBuild:Compile</Generator>
+2 -3
View File
@@ -2,11 +2,10 @@
<UserControl
x:Class="Hyperbar.Windows.PrimaryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="using:Hyperbar.UI.Windows">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ItemsControl
HorizontalAlignment="Center"
ItemTemplateSelector="{Binding Template}"
ItemTemplateSelector="{Binding ViewModelTemplateSelector}"
ItemsSource="{x:Bind ViewModel}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
+2 -2
View File
@@ -4,7 +4,7 @@ using Hyperbar.UI.Windows;
namespace Hyperbar.Widget;
[NotificationHandler(nameof(IWidgetHostViewModel))]
public partial class PrimaryViewModel(IViewModelTemplate template,
public partial class PrimaryViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
@@ -17,6 +17,6 @@ public partial class PrimaryViewModel(IViewModelTemplate template,
[ObservableProperty]
private int index = index;
public IViewModelTemplate Template => template;
public IViewModelTemplateSelector ViewModelTemplateSelector => viewModelTemplateSelector;
}
+2 -3
View File
@@ -2,10 +2,9 @@
<UserControl
x:Class="Hyperbar.Windows.SecondaryView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="using:Hyperbar.UI.Windows">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<ItemsControl ItemTemplateSelector="{Binding Template}" ItemsSource="{x:Bind ViewModel, Mode=OneWay}">
<ItemsControl ItemTemplateSelector="{Binding ViewModelTemplateSelector}" ItemsSource="{x:Bind ViewModel, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel Orientation="Horizontal" />
+3 -3
View File
@@ -10,7 +10,7 @@ public partial class SecondaryViewModel :
[ObservableProperty]
private int index;
public SecondaryViewModel(IViewModelTemplate template,
public SecondaryViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
@@ -18,12 +18,12 @@ public partial class SecondaryViewModel :
IDisposer disposer,
int index) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
{
Template = template;
ViewModelTemplateSelector = viewModelTemplateSelector;
this.index = index;
Add<SettingsButtonViewModel>();
}
public IViewModelTemplate Template { get; }
public IViewModelTemplateSelector ViewModelTemplateSelector { get; }
}
+1 -1
View File
@@ -26,7 +26,7 @@
FontSize="16">
<interactivity:Interaction.Behaviors>
<interactions:EventTriggerBehavior EventName="Click">
<windows:NavigateAction Path="Settings" />
<windows:NavigateAction Name="Settings" />
</interactions:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Button>
+2 -2
View File
@@ -2,12 +2,12 @@
namespace Hyperbar.Windows;
public partial class SettingsButtonViewModel(IViewModelTemplate template,
public partial class SettingsButtonViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
IDisposer disposer) :
ObservableViewModel(serviceProvider, serviceFactory, publisher, disposer)
{
public IViewModelTemplate Template => template;
public IViewModelTemplateSelector ViewModelTemplateSelector => viewModelTemplateSelector;
}
+2 -1
View File
@@ -7,9 +7,10 @@
<MicaBackdrop />
</Window.SystemBackdrop>
<NavigationView
x:Name="Settings"
IsBackButtonVisible="Collapsed"
IsPaneToggleButtonVisible="False"
IsSettingsVisible="False"
MenuItemTemplateSelector="{Binding Template}"
MenuItemTemplateSelector="{Binding ViewModelTemplateSelector}"
MenuItemsSource="{x:Bind ViewModel, Mode=OneWay}" />
</Window>
+1
View File
@@ -4,6 +4,7 @@ using Microsoft.UI.Xaml;
namespace Hyperbar.Windows;
[NavigationTarget("Settings")]
public partial class SettingsView :
Window
{
+3 -3
View File
@@ -5,18 +5,18 @@ namespace Hyperbar.Windows;
public partial class SettingsViewModel :
ObservableCollectionViewModel<INavigationViewModel>
{
public SettingsViewModel(IViewModelTemplate template,
public SettingsViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
{
Template = template;
ViewModelTemplateSelector = viewModelTemplateSelector;
Add<GeneralSettingsNavigationViewModel>("General");
Add<WidgetSettingsNavigationViewModel>("Widgets");
}
public IViewModelTemplate Template { get; }
public IViewModelTemplateSelector ViewModelTemplateSelector { get; }
}
@@ -9,7 +9,7 @@
Content="Widgets">
<interactivity:Interaction.Behaviors>
<interactions:EventTriggerBehavior EventName="Tapped">
<ui:NavigateAction />
<ui:NavigateAction Name="WidgetSettings" TargetName="Settings" />
</interactions:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</NavigationViewItem>
@@ -6,7 +6,4 @@ public class WidgetSettingsNavigationViewModel(IServiceProvider serviceProvider,
ISubscriber subscriber,
IDisposer disposer,
string text) :
NavigationViewModel<WidgetNavigationViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer, text)
{
}
NavigationViewModel<WidgetNavigationViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer, text);
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<UserControl
x:Class="Hyperbar.Windows.WidgetSettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Button>Test</Button>
</Grid>
</UserControl>
@@ -0,0 +1,12 @@
using Microsoft.UI.Xaml.Controls;
namespace Hyperbar.Windows;
public partial class WidgetSettingsView : UserControl
{
public WidgetSettingsView() =>
InitializeComponent();
protected WidgetSettingsViewModel ViewModel =>
(WidgetSettingsViewModel)DataContext;
}
@@ -0,0 +1,19 @@
using Hyperbar.UI.Windows;
namespace Hyperbar.Windows;
public class WidgetSettingsViewModel :
ObservableCollectionViewModel<INavigationViewModel>
{
public WidgetSettingsViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
{
ViewModelTemplateSelector = viewModelTemplateSelector;
}
public IViewModelTemplateSelector ViewModelTemplateSelector { get; }
}
@@ -1,6 +1,6 @@
namespace Hyperbar;
public interface INavigationDescriptor
public interface INavigation
{
Type Type { get; set; }
}
+6
View File
@@ -0,0 +1,6 @@
namespace Hyperbar;
public interface INavigationProvider
{
INavigation? Get(Type type);
}
+6
View File
@@ -0,0 +1,6 @@
namespace Hyperbar;
public interface INavigationTargetProvider
{
object? Get(string name);
}
@@ -3,8 +3,6 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.FileProviders.Physical;
using Microsoft.Extensions.Hosting;
using System.Diagnostics.CodeAnalysis;
using System.Net.Mime;
using System.Text.Json;
namespace Hyperbar;
@@ -140,7 +138,7 @@ public static class IServiceCollectionExtensions
if (contract?.GetGenericArguments() is { Length: 1 } arguments)
{
services.AddTransient<INavigationDescriptor>(provider => new NavigationDescriptor
services.AddTransient<INavigation>(provider => new Navigation
{
Type = arguments[0]
});
@@ -164,7 +162,7 @@ public static class IServiceCollectionExtensions
services.AddKeyedTransient(contentType, key);
services.AddKeyedTransient(templateType, key);
services.AddTransient<IViewModelTemplateDescriptor>(provider => new ViewModelTemplateDescriptor
services.AddTransient<IViewModelTemplate>(provider => new ViewModelTemplate
{
ViewModelType = contentType,
TemplateType = templateType,
@@ -179,7 +177,13 @@ public static class IServiceCollectionExtensions
services.AddSingleton<IServiceFactory>(provider =>
new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!)));
services.AddSingleton<SubscriptionCollection>();
services.AddSingleton<ISubscriptionManager, SubscriptionManager>();
services.AddTransient<ISubscriber, Subscriber>();
services.AddTransient<IPublisher, Publisher>();
services.AddSingleton<IMediator, Mediator>();
services.AddSingleton<IProxyService<IMediator>>(provider =>
new ProxyService<IMediator>(provider.GetRequiredService<IMediator>()));
@@ -1,6 +1,6 @@
namespace Hyperbar;
public interface IViewModelTemplateDescriptor
public interface IViewModelTemplate
{
object Key { get; set; }
+6
View File
@@ -0,0 +1,6 @@
namespace Hyperbar;
public interface IViewModelTemplateProvider
{
IViewModelTemplate? Get(object key);
}
-8
View File
@@ -1,8 +0,0 @@
namespace Hyperbar;
public record Navigate(object Key) :
INotification;
public record Navigate<TView>(TView View, object ViewModel) :
INotification;
-54
View File
@@ -1,54 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
namespace Hyperbar;
public class NavigateHandler :
INotificationHandler<Navigate>
{
private readonly IViewModelTemplateDescriptorProvider contentTemplateDescriptors;
private readonly IServiceProvider provider;
private readonly IPublisher publisher;
private readonly IEnumerable<INavigationDescriptor> navigationDescriptors;
public NavigateHandler(IServiceProvider provider,
IPublisher publisher,
IEnumerable<INavigationDescriptor> navigationDescriptors,
IViewModelTemplateDescriptorProvider contentTemplateDescriptors)
{
this.provider = provider;
this.publisher = publisher;
this.navigationDescriptors = navigationDescriptors;
this.contentTemplateDescriptors = contentTemplateDescriptors;
}
public async Task Handle(Navigate args,
CancellationToken cancellationToken)
{
if (contentTemplateDescriptors.Get(args.Key)
is IViewModelTemplateDescriptor contentTemplateDescriptor)
{
if (navigationDescriptors.FirstOrDefault(x => contentTemplateDescriptor.TemplateType == x.Type ||
contentTemplateDescriptor.TemplateType.BaseType == x.Type) is { } navigationDescriptor)
{
if (contentTemplateDescriptor.TemplateType == navigationDescriptor.Type ||
contentTemplateDescriptor.TemplateType.BaseType == navigationDescriptor.Type)
{
if (provider.GetRequiredKeyedService(contentTemplateDescriptor.TemplateType,
contentTemplateDescriptor.Key) is { } template &&
provider.GetRequiredKeyedService(contentTemplateDescriptor.ViewModelType,
contentTemplateDescriptor.Key) is { } content)
{
Type navigateType = typeof(Navigate<>)
.MakeGenericType(navigationDescriptor.Type);
if (Activator.CreateInstance(navigateType,
new object[] { template, content }) is object navigate)
{
await publisher.PublishAsync(navigate, cancellationToken);
}
}
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More