Get ContentControl navigation working
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
}
|
||||
@@ -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
-13
@@ -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""
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
@@ -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>();
|
||||
})
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
@@ -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,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>
|
||||
|
||||
@@ -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,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" />
|
||||
|
||||
@@ -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; }
|
||||
|
||||
}
|
||||
@@ -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,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;
|
||||
}
|
||||
@@ -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>
|
||||
@@ -4,6 +4,7 @@ using Microsoft.UI.Xaml;
|
||||
|
||||
namespace Hyperbar.Windows;
|
||||
|
||||
[NavigationTarget("Settings")]
|
||||
public partial class SettingsView :
|
||||
Window
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface INavigationProvider
|
||||
{
|
||||
INavigation? Get(Type type);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface INavigationTargetProvider
|
||||
{
|
||||
object? Get(string name);
|
||||
}
|
||||
+8
-4
@@ -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; }
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IViewModelTemplateProvider
|
||||
{
|
||||
IViewModelTemplate? Get(object key);
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public record Navigate(object Key) :
|
||||
INotification;
|
||||
|
||||
public record Navigate<TView>(TView View, object ViewModel) :
|
||||
INotification;
|
||||
@@ -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
Reference in New Issue
Block a user