This commit is contained in:
TheXamlGuy
2024-02-14 22:54:22 +00:00
parent 9fe2317c4f
commit cc61842c9a
23 changed files with 138 additions and 93 deletions
@@ -0,0 +1,19 @@
using Microsoft.UI.Xaml.Controls;
namespace Hyperbar.UI.Windows;
public class ContentControlHandler(IViewModelContentBinder viewModelContentBinder) :
INavigationHandler<ContentControl>
{
public Task Handle(Navigate<ContentControl> args,
CancellationToken cancellationToken)
{
if (args.Target is ContentControl contentControl)
{
contentControl.Content = args.View;
contentControl.DataContext = args.ViewModel;
}
return Task.CompletedTask;
}
}
-16
View File
@@ -1,23 +1,7 @@
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Hyperbar.UI.Windows; namespace Hyperbar.UI.Windows;
public class ContentControlHandler(IViewModelContentBinder viewModelContentBinder) :
INavigationHandler<ContentControl>
{
public Task Handle(Navigate<ContentControl> args,
CancellationToken cancellationToken)
{
if (args.Target is ContentControl contentControl)
{
contentControl.Content = args.View;
}
return Task.CompletedTask;
}
}
public class WindowHandler(IViewModelContentBinder viewModelContentBinder) : public class WindowHandler(IViewModelContentBinder viewModelContentBinder) :
INavigationHandler<Window> INavigationHandler<Window>
{ {
@@ -8,9 +8,9 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<None Remove="WidgetConfigurationNavigationView.xaml" />
<None Remove="WidgetConfigurationView.xaml" />
<None Remove="WidgetNavigationView.xaml" /> <None Remove="WidgetNavigationView.xaml" />
<None Remove="WidgetSettingsNavigationView.xaml" />
<None Remove="WidgetSettingsView.xaml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240124002-experimental2" /> <PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240124002-experimental2" />
@@ -24,7 +24,7 @@
<ProjectReference Include="..\Hyperbar\Hyperbar.csproj" /> <ProjectReference Include="..\Hyperbar\Hyperbar.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Update="WidgetSettingsNavigationView.xaml"> <Page Update="WidgetConfigurationNavigationView.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime> <XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
@@ -32,7 +32,7 @@
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime> <XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="WidgetSettingsView.xaml"> <Page Update="WidgetConfigurationView.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime> <XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
@@ -36,8 +36,8 @@ public static class IServiceCollectionExtensions
services.AddContentTemplate<WidgetButtonViewModel, WidgetButtonView>(); services.AddContentTemplate<WidgetButtonViewModel, WidgetButtonView>();
services.AddContentTemplate<WidgetSplitButtonViewModel, WidgetSplitButtonView>(); services.AddContentTemplate<WidgetSplitButtonViewModel, WidgetSplitButtonView>();
services.AddContentTemplate<WidgetSettingsNavigationViewModel, WidgetSettingsNavigationView>(); services.AddContentTemplate<WidgetConfigurationNavigationViewModel, WidgetConfigurationNavigationView>();
services.AddContentTemplate<WidgetSettingsViewModel, WidgetSettingsView>("WidgetSettings"); services.AddContentTemplate<WidgetConfigurationViewModel, WidgetConfigurationView>("WidgetSettings");
}))); })));
return services; return services;
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<NavigationViewItem <NavigationViewItem
x:Class="Hyperbar.Widget.Windows.WidgetSettingsNavigationView" x:Class="Hyperbar.Widget.Windows.WidgetConfigurationNavigationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core" xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
@@ -2,9 +2,9 @@ using Microsoft.UI.Xaml.Controls;
namespace Hyperbar.Widget.Windows; namespace Hyperbar.Widget.Windows;
public sealed partial class WidgetSettingsNavigationView : public sealed partial class WidgetConfigurationNavigationView :
NavigationViewItem NavigationViewItem
{ {
public WidgetSettingsNavigationView() => public WidgetConfigurationNavigationView() =>
InitializeComponent(); InitializeComponent();
} }
@@ -1,6 +1,6 @@
namespace Hyperbar.Widget.Windows; namespace Hyperbar.Widget.Windows;
public class WidgetSettingsNavigationViewModel(IServiceProvider serviceProvider, public class WidgetConfigurationNavigationViewModel(IServiceProvider serviceProvider,
IServiceFactory serviceFactory, IServiceFactory serviceFactory,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscriber subscriber,
@@ -2,19 +2,19 @@
namespace Hyperbar.Widget.Windows; namespace Hyperbar.Widget.Windows;
public class WidgetSettingsNavigationViewModelEnumerator(IPublisher publisher, public class WidgetConfigurationNavigationViewModelEnumerator(IPublisher publisher,
IWidgetHostCollection widgetHosts) : IWidgetHostCollection widgetHosts) :
INotificationHandler<Enumerate<WidgetSettingsNavigationViewModel>> INotificationHandler<Enumerate<WidgetConfigurationNavigationViewModel>>
{ {
public async Task Handle(Enumerate<WidgetSettingsNavigationViewModel> args, public async Task Handle(Enumerate<WidgetConfigurationNavigationViewModel> args,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
foreach (IWidgetHost host in widgetHosts) foreach (IWidgetHost host in widgetHosts)
{ {
if (host.Services.GetService<IServiceFactory>() is IServiceFactory serviceFactory) if (host.Services.GetService<IServiceFactory>() is IServiceFactory serviceFactory)
{ {
await publisher.PublishAsync(new Create<WidgetSettingsNavigationViewModel>(serviceFactory await publisher.PublishAsync(new Create<WidgetConfigurationNavigationViewModel>(serviceFactory
.Create<WidgetSettingsNavigationViewModel>(host.Configuration.Name)), .Create<WidgetConfigurationNavigationViewModel>(host.Configuration.Name)),
nameof(WidgetNavigationViewModel), cancellationToken); nameof(WidgetNavigationViewModel), cancellationToken);
} }
} }
@@ -1,9 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<UserControl <UserControl
x:Class="Hyperbar.Widget.Windows.WidgetSettingsView" x:Class="Hyperbar.Widget.Windows.WidgetConfigurationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid> <ListBox ItemsSource="{Binding Mode=TwoWay}" />
<Button>Test</Button>
</Grid>
</UserControl> </UserControl>
@@ -0,0 +1,12 @@
using Microsoft.UI.Xaml.Controls;
namespace Hyperbar.Widget.Windows;
public partial class WidgetConfigurationView : UserControl
{
public WidgetConfigurationView() =>
InitializeComponent();
protected WidgetConfigurationViewModel ViewModel =>
(WidgetConfigurationViewModel)DataContext;
}
@@ -0,0 +1,51 @@
using Hyperbar.UI.Windows;
namespace Hyperbar.Widget.Windows;
public class WidgetConfigurationViewModel<TConfiguration, TValue> :
ValueViewModel<TValue>,
INotificationHandler<Changed<TConfiguration>>
where TConfiguration :
class
{
private readonly Func<TConfiguration, TValue> valueFactory;
public WidgetConfigurationViewModel(IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
IDisposer disposer,
Func<TConfiguration, TValue> valueFactory) : base(serviceProvider, serviceFactory, publisher, disposer)
{
this.valueFactory = valueFactory;
}
public Task Handle(Changed<TConfiguration> args,
CancellationToken cancellationToken = default)
{
if (args.Value is TConfiguration configuration)
{
valueFactory.Invoke(configuration);
}
return Task.CompletedTask;
}
}
public class WidgetConfigurationViewModel :
ObservableCollectionViewModel<IObservableViewModel>
{
public WidgetConfigurationViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer)
{
ViewModelTemplateSelector = viewModelTemplateSelector;
Add<WidgetConfigurationViewModel<WidgetAvailability,
bool>>((Func<WidgetAvailability, bool>)(config => config.Value));
}
public IViewModelTemplateSelector ViewModelTemplateSelector { get; }
}
@@ -10,7 +10,7 @@ public class WidgetNavigationViewModel(IViewModelTemplateSelector viewModelTempl
ISubscriber subscriber, ISubscriber subscriber,
IDisposer disposer, IDisposer disposer,
string text) : string text) :
NavigationViewModel<WidgetSettingsNavigationViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer, text) NavigationViewModel<WidgetConfigurationNavigationViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer, text)
{ {
public IViewModelTemplateSelector ViewModelTemplateSelector => viewModelTemplateSelector; public IViewModelTemplateSelector ViewModelTemplateSelector => viewModelTemplateSelector;
} }
@@ -1,12 +0,0 @@
using Microsoft.UI.Xaml.Controls;
namespace Hyperbar.Widget.Windows;
public partial class WidgetSettingsView : UserControl
{
public WidgetSettingsView() =>
InitializeComponent();
protected WidgetSettingsViewModel ViewModel =>
(WidgetSettingsViewModel)DataContext;
}
@@ -1,14 +0,0 @@
using Hyperbar.UI.Windows;
namespace Hyperbar.Widget.Windows;
public class WidgetSettingsViewModel(IViewModelTemplateSelector viewModelTemplateSelector,
IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer) :
ObservableCollectionViewModel<IObservableViewModel>(serviceProvider, serviceFactory, publisher, subscriber, disposer)
{
public IViewModelTemplateSelector ViewModelTemplateSelector => viewModelTemplateSelector;
}
+17 -19
View File
@@ -5,23 +5,21 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core" xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"> xmlns:interactivity="using:Microsoft.Xaml.Interactivity">
<Grid> <ItemsControl ItemTemplateSelector="{Binding ViewModelTemplateSelector}" ItemsSource="{Binding Mode=TwoWay}">
<ItemsControl ItemTemplateSelector="{Binding ViewModelTemplateSelector}" ItemsSource="{Binding Mode=TwoWay}"> <ItemsControl.ItemsPanel>
<ItemsControl.ItemsPanel> <ItemsPanelTemplate>
<ItemsPanelTemplate> <StackPanel Orientation="Horizontal" Spacing="8" />
<StackPanel Orientation="Horizontal" Spacing="8" /> </ItemsPanelTemplate>
</ItemsPanelTemplate> </ItemsControl.ItemsPanel>
</ItemsControl.ItemsPanel> <ItemsControl.ItemContainerTransitions>
<ItemsControl.ItemContainerTransitions> <TransitionCollection>
<TransitionCollection> <AddDeleteThemeTransition />
<AddDeleteThemeTransition /> </TransitionCollection>
</TransitionCollection> </ItemsControl.ItemContainerTransitions>
</ItemsControl.ItemContainerTransitions> <interactivity:Interaction.Behaviors>
<interactivity:Interaction.Behaviors> <interactions:EventTriggerBehavior EventName="Loaded">
<interactions:EventTriggerBehavior EventName="Loaded"> <interactions:InvokeCommandAction Command="{Binding InitializeCommand}" />
<interactions:InvokeCommandAction Command="{Binding InitializeCommand}" /> </interactions:EventTriggerBehavior>
</interactions:EventTriggerBehavior> </interactivity:Interaction.Behaviors>
</interactivity:Interaction.Behaviors> </ItemsControl>
</ItemsControl>
</Grid>
</UserControl> </UserControl>
+1 -1
View File
@@ -42,7 +42,7 @@ public class WidgetBuilder :
services.AddSingleton<IDisposer, Disposer>(); services.AddSingleton<IDisposer, Disposer>();
services.AddHandler<WidgetAvailabilityChangedHandler>(); services.AddHandler<WidgetAvailabilityChangedHandler>();
services.AddValueChangedNotification<WidgetConfiguration, services.AddConfigurationChanged<WidgetConfiguration,
WidgetAvailability>((config) => (args) => WidgetAvailability>((config) => (args) =>
{ {
args.Value = config.IsEnabled; args.Value = config.IsEnabled;
@@ -1,7 +1,7 @@
namespace Hyperbar.Widget; namespace Hyperbar.Widget;
public class WidgetConfigurationHandler(IEnumerable<IConfigurationValueChangedNotification<WidgetConfiguration>> public class WidgetConfigurationHandler(IEnumerable<IConfigurationChangedPublisher<WidgetConfiguration>>
configurationValueChangedNotifications ) : configurationValueChangedNotifications) :
INotificationHandler<Changed<WidgetConfiguration>> INotificationHandler<Changed<WidgetConfiguration>>
{ {
public async Task Handle(Changed<WidgetConfiguration> args, public async Task Handle(Changed<WidgetConfiguration> args,
@@ -9,7 +9,7 @@ public class WidgetConfigurationHandler(IEnumerable<IConfigurationValueChangedNo
{ {
if (args.Value is WidgetConfiguration configuration) if (args.Value is WidgetConfiguration configuration)
{ {
foreach (IConfigurationValueChangedNotification<WidgetConfiguration> notification in foreach (IConfigurationChangedPublisher<WidgetConfiguration> notification in
configurationValueChangedNotifications) configurationValueChangedNotifications)
{ {
await notification.PublishAsync(configuration); await notification.PublishAsync(configuration);
+1 -1
View File
@@ -63,7 +63,7 @@ public partial class App :
services.AddContentTemplate<GeneralSettingsNavigationViewModel, GeneralSettingsNavigationView>(); services.AddContentTemplate<GeneralSettingsNavigationViewModel, GeneralSettingsNavigationView>();
services.AddContentTemplate<WidgetNavigationViewModel, WidgetNavigationView>(); services.AddContentTemplate<WidgetNavigationViewModel, WidgetNavigationView>();
services.AddHandler<WidgetSettingsNavigationViewModelEnumerator>(); services.AddHandler<WidgetConfigurationNavigationViewModelEnumerator>();
services.AddTransient<IInitializer, AppInitializer>(); services.AddTransient<IInitializer, AppInitializer>();
}) })
.Build(); .Build();
@@ -1,8 +1,8 @@
namespace Hyperbar; namespace Hyperbar;
public class ConfigurationValueChangedNotification<TConfiguration, TValue>(IPublisher publisher, public class ConfigurationChangedPublisher<TConfiguration, TValue>(IPublisher publisher,
Func<TConfiguration, Action<TValue>> factory) : Func<TConfiguration, Action<TValue>> factory) :
IConfigurationValueChangedNotification<TConfiguration> IConfigurationChangedPublisher<TConfiguration>
where TConfiguration : where TConfiguration :
class class
where TValue : where TValue :
@@ -1,6 +1,6 @@
namespace Hyperbar; namespace Hyperbar;
public interface IConfigurationValueChangedNotification<TConfiguration> public interface IConfigurationChangedPublisher<TConfiguration>
{ {
Task PublishAsync(TConfiguration configuration); Task PublishAsync(TConfiguration configuration);
} }
+3 -3
View File
@@ -10,15 +10,15 @@ namespace Hyperbar;
public static class IServiceCollectionExtensions public static class IServiceCollectionExtensions
{ {
public static IServiceCollection AddValueChangedNotification<TConfiguration, TValue>(this IServiceCollection services, public static IServiceCollection AddConfigurationChanged<TConfiguration, TValue>(this IServiceCollection services,
Func<TConfiguration, Action<TValue>> factory) Func<TConfiguration, Action<TValue>> factory)
where TConfiguration : where TConfiguration :
class class
where TValue : where TValue :
class, new() class, new()
{ {
services.AddSingleton<IConfigurationValueChangedNotification<TConfiguration>>(provider => services.AddSingleton<IConfigurationChangedPublisher<TConfiguration>>(provider =>
new ConfigurationValueChangedNotification<TConfiguration, TValue>(provider.GetRequiredService<IPublisher>(), new ConfigurationChangedPublisher<TConfiguration, TValue>(provider.GetRequiredService<IPublisher>(),
factory)); factory));
return services; return services;
@@ -7,7 +7,6 @@ using System.Reactive.Disposables;
using System.Windows.Input; using System.Windows.Input;
namespace Hyperbar; namespace Hyperbar;
public partial class ObservableCollectionViewModel<TViewModel> : public partial class ObservableCollectionViewModel<TViewModel> :
ObservableObject, ObservableObject,
IObservableCollectionViewModel<TViewModel>, IObservableCollectionViewModel<TViewModel>,
+10
View File
@@ -0,0 +1,10 @@
namespace Hyperbar;
public partial class ValueViewModel<TValue>(IServiceProvider serviceProvider,
IServiceFactory serviceFactory,
IPublisher publisher,
IDisposer disposer) :
ObservableViewModel(serviceProvider, serviceFactory, publisher, disposer)
{
public TValue? Value { get; set; }
}