Add KeyBindingBehavior

This commit is contained in:
TheXamlGuy
2024-04-22 22:30:57 +01:00
parent 5cb7ea538e
commit 7fa80371a4
16 changed files with 77 additions and 32 deletions
+6 -3
View File
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
@@ -35,12 +36,14 @@ public class ComponentInitializer(IEnumerable<IComponent> components,
provider.GetRequiredService<IComponentScopeProvider>()); provider.GetRequiredService<IComponentScopeProvider>());
services.AddRange(typedServices.Services); services.AddRange(typedServices.Services);
services.AddSingleton(new ComponentScope(component.GetType().Name));
}); });
IComponentHost host = builder.Build(); IComponentHost host = builder.Build();
scopes.Add(component.GetType().Name, scopes.Add(new ComponentScopeDescriptor(component.GetType().Name,
host.Services.GetRequiredService<IServiceProvider>()); provider.GetRequiredService<IServiceProvider>()));
hosts.Add(host); hosts.Add(host);
await host.StartAsync(); await host.StartAsync();
+3
View File
@@ -0,0 +1,3 @@
namespace Toolkit.Foundation;
public record ComponentScope(string Name);
@@ -1,4 +1,4 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public class ComponentScopeCollection : Dictionary<string, IServiceProvider>, public class ComponentScopeCollection : List<ComponentScopeDescriptor>,
IComponentScopeCollection; IComponentScopeCollection;
@@ -0,0 +1,3 @@
namespace Toolkit.Foundation;
public record ComponentScopeDescriptor(string Key, IServiceProvider Services);
+4 -5
View File
@@ -3,10 +3,9 @@
public class ComponentScopeProvider(IComponentScopeCollection scopes) : public class ComponentScopeProvider(IComponentScopeCollection scopes) :
IComponentScopeProvider IComponentScopeProvider
{ {
public IServiceProvider? Get(string name) public ComponentScopeDescriptor? Get(string key)
{ {
return scopes.TryGetValue(name, return scopes.FirstOrDefault(x => x.Key == key) is ComponentScopeDescriptor
out IServiceProvider? scope) ? scope : default; descriptor ? descriptor : default;
} }
} }
@@ -1,8 +1,8 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public class Configuration<TConfiguration>(string section, public class ConfigurationDescriptor<TConfiguration>(string section,
IConfigurationReader<TConfiguration> reader) : IConfigurationReader<TConfiguration> reader) :
IConfiguration<TConfiguration> IConfigurationDescriptor<TConfiguration>
where TConfiguration : where TConfiguration :
class class
{ {
@@ -1,6 +1,4 @@
using System.Xml.Linq; namespace Toolkit.Foundation;
namespace Toolkit.Foundation;
public class ContentTemplateDescriptorProvider(IEnumerable<IContentTemplateDescriptor> contentTemplates) : public class ContentTemplateDescriptorProvider(IEnumerable<IContentTemplateDescriptor> contentTemplates) :
IContentTemplateDescriptorProvider IContentTemplateDescriptorProvider
+3 -2
View File
@@ -49,10 +49,11 @@ public class DefaultBuilder :
services.AddTransient<INavigationContextProvider, NavigationContextProvider>(); services.AddTransient<INavigationContextProvider, NavigationContextProvider>();
services.AddTransient<INavigationScope, NavigationScope>(); services.AddTransient<INavigationScope, NavigationScope>();
services.AddSingleton(new ComponentScope("Root"));
services.AddScoped<IComponentScopeCollection, ComponentScopeCollection>(provider => new ComponentScopeCollection services.AddScoped<IComponentScopeCollection, ComponentScopeCollection>(provider => new ComponentScopeCollection
{ {
{ "Default", provider.GetRequiredService<IServiceProvider>() } new ComponentScopeDescriptor("Root", provider.GetRequiredService<IServiceProvider>())
}); });
services.AddTransient<IComponentScopeProvider, ComponentScopeProvider>(); services.AddTransient<IComponentScopeProvider, ComponentScopeProvider>();
@@ -1,5 +1,5 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public interface IComponentScopeCollection : public interface IComponentScopeCollection :
IDictionary<string, IServiceProvider>; IList<ComponentScopeDescriptor>;
@@ -2,6 +2,6 @@
public interface IComponentScopeProvider public interface IComponentScopeProvider
{ {
IServiceProvider? Get(string name); ComponentScopeDescriptor? Get(string key);
} }
@@ -1,6 +1,6 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public interface IConfiguration<out TConfiguration> public interface IConfigurationDescriptor<out TConfiguration>
where TConfiguration : where TConfiguration :
class class
{ {
@@ -3,9 +3,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.FileProviders.Physical; using Microsoft.Extensions.FileProviders.Physical;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using System;
using System.Text.Json; using System.Text.Json;
using Toolkit.Foundation;
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
@@ -145,11 +143,11 @@ public static class IServiceCollectionExtensions
services.AddTransient<IWritableConfiguration<TConfiguration>, WritableConfiguration<TConfiguration>>(); services.AddTransient<IWritableConfiguration<TConfiguration>, WritableConfiguration<TConfiguration>>();
services.TryAddKeyedTransient<IConfiguration<TConfiguration>>(section, (provider, key) => services.TryAddKeyedTransient<IConfigurationDescriptor<TConfiguration>>(section, (provider, key) =>
new Configuration<TConfiguration>(section, provider.GetRequiredKeyedService<IConfigurationReader<TConfiguration>>(key))); new ConfigurationDescriptor<TConfiguration>(section, provider.GetRequiredKeyedService<IConfigurationReader<TConfiguration>>(key)));
services.AddTransient(provider => provider.GetRequiredKeyedService<IConfiguration<TConfiguration>>(section)); services.AddTransient(provider => provider.GetRequiredKeyedService<IConfigurationDescriptor<TConfiguration>>(section));
services.AddTransient(provider => provider.GetRequiredKeyedService<IConfiguration<TConfiguration>>(section).Value); services.AddTransient(provider => provider.GetRequiredKeyedService<IConfigurationDescriptor<TConfiguration>>(section).Value);
return services; return services;
} }
+3 -3
View File
@@ -8,10 +8,10 @@ public class NavigateBackHandler(IComponentScopeProvider provider) :
public async Task Handle(NavigateBack args, public async Task Handle(NavigateBack args,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
if (provider.Get(args.Scope ?? "Default") if (provider.Get(args.Scope ?? "Root")
is IServiceProvider scope) is ComponentScopeDescriptor descriptor)
{ {
if (scope.GetService<INavigationScope>() is INavigationScope navigationScope) if (descriptor?.Services?.GetService<INavigationScope>() is INavigationScope navigationScope)
{ {
await navigationScope.NavigateBackAsync(args.Context, cancellationToken); await navigationScope.NavigateBackAsync(args.Context, cancellationToken);
} }
+5 -4
View File
@@ -2,16 +2,17 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public class NavigateHandler(IComponentScopeProvider provider) : public class NavigateHandler(ComponentScope scope,
IComponentScopeProvider provider) :
INotificationHandler<Navigate> INotificationHandler<Navigate>
{ {
public async Task Handle(Navigate args, public async Task Handle(Navigate args,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
if (provider.Get(args.Scope ?? "Default") if (provider.Get(args.Scope ?? scope.Name)
is IServiceProvider scope) is ComponentScopeDescriptor descriptor)
{ {
if (scope.GetService<INavigationScope>() is INavigationScope navigationScope) if (descriptor?.Services?.GetService<INavigationScope>() is INavigationScope navigationScope)
{ {
await navigationScope.NavigateAsync(args.Route, args.Sender, await navigationScope.NavigateAsync(args.Route, args.Sender,
args.Context, args.Navigated, args.Parameters, cancellationToken); args.Context, args.Navigated, args.Parameters, cancellationToken);
@@ -2,6 +2,7 @@
using Avalonia.Xaml.Interactivity; using Avalonia.Xaml.Interactivity;
namespace Toolkit.UI.Avalonia; namespace Toolkit.UI.Avalonia;
public class ComparisonCondition : public class ComparisonCondition :
AvaloniaObject, AvaloniaObject,
ICondition ICondition
+38
View File
@@ -0,0 +1,38 @@
using Avalonia;
using Avalonia.Input;
using Avalonia.Xaml.Interactivity;
using System.Windows.Input;
namespace Toolkit.UI.Avalonia;
public class KeyBindingBehavior :
Trigger<InputElement>,
ICommand
{
public static readonly StyledProperty<KeyBinding> KeyBindingProperty =
AvaloniaProperty.Register<KeyBindingBehavior, KeyBinding>(nameof(KeyBinding));
public KeyBinding KeyBinding
{
get => GetValue(KeyBindingProperty);
set => SetValue(KeyBindingProperty, value);
}
public event EventHandler? CanExecuteChanged;
protected override void OnAttached()
{
if (KeyBinding != null)
{
KeyBinding.Command = this;
AssociatedObject?.KeyBindings.Add(KeyBinding);
}
base.OnAttached();
}
public bool CanExecute(object? parameter) => true;
public void Execute(object? parameter) =>
Interaction.ExecuteActions(AssociatedObject, Actions, null);
}