From 5740e03ba1978e570975af3df2845b2473985592 Mon Sep 17 00:00:00 2001 From: Dan Clark Date: Wed, 12 Feb 2025 20:59:38 +0000 Subject: [PATCH] Fix region bug --- Toolkit.Foundation/ComponentFactory.cs | 2 +- Toolkit.Foundation/ComponentInitializer.cs | 2 +- Toolkit.Foundation/DefaultHostBuilder.cs | 47 ++++++-- Toolkit.Foundation/INavigation.cs | 6 -- Toolkit.Foundation/IScopedServiceFactory.cs | 2 +- Toolkit.Foundation/IScopedServiceProvider.cs | 6 +- .../IServiceCollectionExtensions.cs | 18 ++-- Toolkit.Foundation/NavigateEventArgs.cs | 3 +- Toolkit.Foundation/NavigateHandler.cs | 101 +++++++++++++++--- Toolkit.Foundation/NavigateScope.cs | 8 ++ Toolkit.Foundation/Navigation.cs | 77 +------------ Toolkit.Foundation/NotificationAttribute.cs | 10 -- Toolkit.Foundation/ObjectExtensions.cs | 26 +++-- Toolkit.Foundation/Observable.cs | 22 +++- Toolkit.Foundation/ObservableCollection.cs | 24 ++++- Toolkit.Foundation/ObservableConfiguration.cs | 4 +- .../ObservableConfigurationCollection.cs | 4 +- .../{NamedComponent.cs => Scoped.cs} | 2 +- Toolkit.Foundation/ScopedServiceFactory.cs | 10 +- Toolkit.Foundation/ScopedServiceProvider.cs | 14 ++- Toolkit.UI.Avalonia/NavigateAction.cs | 10 +- .../ItemContainerInvokedBehavior.cs | 1 - Toolkit.UI.WinUI/MediaPlayerBehavior.cs | 47 ++++++++ Toolkit.UI.WinUI/NavigateAction.cs | 14 ++- 24 files changed, 277 insertions(+), 183 deletions(-) create mode 100644 Toolkit.Foundation/NavigateScope.cs delete mode 100644 Toolkit.Foundation/NotificationAttribute.cs rename Toolkit.Foundation/{NamedComponent.cs => Scoped.cs} (66%) create mode 100644 Toolkit.UI.WinUI/MediaPlayerBehavior.cs diff --git a/Toolkit.Foundation/ComponentFactory.cs b/Toolkit.Foundation/ComponentFactory.cs index 5d01187..5ca84c1 100644 --- a/Toolkit.Foundation/ComponentFactory.cs +++ b/Toolkit.Foundation/ComponentFactory.cs @@ -47,7 +47,7 @@ public class ComponentFactory(IServiceProvider provider, provider.GetRequiredService()); services.AddRange(proxy.Services); - services.AddSingleton(new NamedComponent(key)); + services.AddSingleton(new Scoped(key)); if (servicesDelegate is not null) { diff --git a/Toolkit.Foundation/ComponentInitializer.cs b/Toolkit.Foundation/ComponentInitializer.cs index 970d277..ea0ecfc 100644 --- a/Toolkit.Foundation/ComponentInitializer.cs +++ b/Toolkit.Foundation/ComponentInitializer.cs @@ -38,7 +38,7 @@ public class ComponentInitializer(IEnumerable components, services.AddRange(typedServices.Services); - services.AddSingleton(new NamedComponent(component.GetType().Name)); + services.AddSingleton(new Scoped(component.GetType().Name)); }); IComponentHost host = builder.Build(); diff --git a/Toolkit.Foundation/DefaultHostBuilder.cs b/Toolkit.Foundation/DefaultHostBuilder.cs index 89f27e9..13255de 100644 --- a/Toolkit.Foundation/DefaultHostBuilder.cs +++ b/Toolkit.Foundation/DefaultHostBuilder.cs @@ -1,6 +1,7 @@ using CommunityToolkit.Mvvm.Messaging; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using System; namespace Toolkit.Foundation; @@ -38,26 +39,54 @@ public class DefaultHostBuilder : services.AddTransient(); - services.AddSingleton(); + services.AddScoped(); services.AddTransient(); services.AddScoped(); - services.AddSingleton(new NamedComponent("Root")); - services.AddScoped(provider => - [ - new ComponentScopeDescriptor("Root", provider.GetRequiredService()) - ]); + services.AddTransient>(provider => Comparer.Create((x, z) => + StringComparer.CurrentCultureIgnoreCase.Compare(x.Key, z.Key))); - services.AddTransient(); - services.AddTransient(); + Scoped named = new("Root"); + services.AddSingleton>(provider => + { + ScopedServiceDescriptor descriptor = new(); + descriptor.Set(named); + + return descriptor; + }); + + services.AddSingleton(provider => provider.GetRequiredService>().Value!); + + services.AddSingleton>(provider => + { + Cache cache = new(provider.GetRequiredService>()) + { + { named, provider } + }; + + return cache; + }); + + services.AddTransient(provider => provider.GetService>()!.Select(x => x.Value)); + + services.AddTransient, ScopedServiceProvider>(); + services.AddTransient, ScopedServiceFactory>(); + + //services.AddScoped(provider => + //[ + // new ComponentScopeDescriptor("Root", provider.GetRequiredService()) + //]); + + //services.AddTransient(); + //services.AddTransient(); services.AddScopedHandler(); services.AddScopedHandler(); services.AddTransient(); - services.AddInitialization(); + //services.AddInitialization(); }); builderDelegate.Invoke(hostBuilder); diff --git a/Toolkit.Foundation/INavigation.cs b/Toolkit.Foundation/INavigation.cs index b47e408..facdd90 100644 --- a/Toolkit.Foundation/INavigation.cs +++ b/Toolkit.Foundation/INavigation.cs @@ -2,11 +2,5 @@ public interface INavigation { - void Navigate(string route, - object? sender = null, - object? region = null, - EventHandler? navigated = null, - IDictionary? parameters = null); - void Back(object? region); } \ No newline at end of file diff --git a/Toolkit.Foundation/IScopedServiceFactory.cs b/Toolkit.Foundation/IScopedServiceFactory.cs index a2b4ef8..128b3e8 100644 --- a/Toolkit.Foundation/IScopedServiceFactory.cs +++ b/Toolkit.Foundation/IScopedServiceFactory.cs @@ -4,5 +4,5 @@ namespace Toolkit.Foundation; public interface IScopedServiceFactory { - (IServiceScope, TService) Create(params object?[] parameters); + (IServiceProvider, TService) Create(params object?[] parameters); } \ No newline at end of file diff --git a/Toolkit.Foundation/IScopedServiceProvider.cs b/Toolkit.Foundation/IScopedServiceProvider.cs index 1e25f01..65c8a4c 100644 --- a/Toolkit.Foundation/IScopedServiceProvider.cs +++ b/Toolkit.Foundation/IScopedServiceProvider.cs @@ -1,8 +1,6 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Toolkit.Foundation; +namespace Toolkit.Foundation; public interface IScopedServiceProvider { - bool TryGet(TService service, out IServiceScope? serviceScope); + bool TryGet(TService service, out IServiceProvider? serviceProvider); } \ No newline at end of file diff --git a/Toolkit.Foundation/IServiceCollectionExtensions.cs b/Toolkit.Foundation/IServiceCollectionExtensions.cs index 1a3b567..cbbb150 100644 --- a/Toolkit.Foundation/IServiceCollectionExtensions.cs +++ b/Toolkit.Foundation/IServiceCollectionExtensions.cs @@ -50,11 +50,11 @@ public static class IServiceCollectionExtensions return services; } - public static IServiceCollection AddAsyncHandlerScoped(this IServiceCollection services, + public static IServiceCollection AddScopedAsyncHandler(this IServiceCollection services, string key) where THandler : class, IAsyncHandler - where TMessage : class => AddAsyncHandlerScoped(services, ServiceLifetime.Transient, key); + where TMessage : class => AddScopedAsyncHandler(services, ServiceLifetime.Transient, key); - public static IServiceCollection AddAsyncHandlerScoped(this IServiceCollection services, + public static IServiceCollection AddScopedAsyncHandler(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Transient, string? key = null) where THandler : class, IAsyncHandler where TMessage : class @@ -77,11 +77,11 @@ public static class IServiceCollectionExtensions return services; } - public static IServiceCollection AddAsyncHandlerScoped(this IServiceCollection services, + public static IServiceCollection AddScopedAsyncHandler(this IServiceCollection services, string key) where THandler : class, IAsyncHandler - where TMessage : class => AddAsyncHandlerScoped(services, ServiceLifetime.Transient, key); + where TMessage : class => AddScopedAsyncHandler(services, ServiceLifetime.Transient, key); - public static IServiceCollection AddAsyncHandlerScoped(this IServiceCollection services, + public static IServiceCollection AddScopedAsyncHandler(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Transient, string? key = null) where THandler : class, IAsyncHandler where TMessage : class @@ -357,7 +357,7 @@ public static class IServiceCollectionExtensions services.AddScoped, ScopedServiceDescriptor>(); services.AddScoped(provider => provider.GetRequiredService>().Value!); - services.AddCache(); + services.AddCache(); services.AddTransient, ScopedServiceProvider>(); services.AddTransient, ScopedServiceFactory>(); @@ -372,7 +372,7 @@ public static class IServiceCollectionExtensions services.AddScoped, ScopedServiceDescriptor>(); services.AddScoped(provider => provider.GetRequiredService>().Value!); - services.AddCache(); + services.AddCache(); services.AddTransient, ScopedServiceProvider>(); services.AddTransient, ScopedServiceFactory>(provider => @@ -380,7 +380,7 @@ public static class IServiceCollectionExtensions providerDelegate.Invoke(provider); IServiceScopeFactory factory = provider.GetRequiredService(); - ICache cache = provider.GetRequiredService>(); + ICache cache = provider.GetRequiredService>(); return new ScopedServiceFactory(factory, cache); }); diff --git a/Toolkit.Foundation/NavigateEventArgs.cs b/Toolkit.Foundation/NavigateEventArgs.cs index f071fea..11e68a0 100644 --- a/Toolkit.Foundation/NavigateEventArgs.cs +++ b/Toolkit.Foundation/NavigateEventArgs.cs @@ -2,7 +2,6 @@ public record NavigateEventArgs(string Route, object? Region = null, - string? Scope = null, + NavigateScope? Scope = null, object? Sender = null, - EventHandler? Navigated = null, IDictionary? Parameters = null); diff --git a/Toolkit.Foundation/NavigateHandler.cs b/Toolkit.Foundation/NavigateHandler.cs index 17e6c72..48569aa 100644 --- a/Toolkit.Foundation/NavigateHandler.cs +++ b/Toolkit.Foundation/NavigateHandler.cs @@ -1,38 +1,109 @@ -using Microsoft.Extensions.DependencyInjection; +using CommunityToolkit.Mvvm.Messaging; +using Microsoft.Extensions.DependencyInjection; namespace Toolkit.Foundation; -public class NavigateHandler(NamedComponent named, - IComponentScopeProvider componentScopeProvider) : +public class NavigateHandler(Scoped scoped, + IScopedServiceProvider scopedServiceProvider) : IHandler { public void Handle(NavigateEventArgs args) { - INavigation? navigation = null; - if (args.Scope is "self" || args.Scope is "new") + object? region = args.Region; + string route = args.Route; + IDictionary? parameters = null; + object? sender = args.Sender; + + string[] segments = route.Split('/'); + + object? resolvedRegion = region is "self" ? "self" : null; + IServiceProvider? serviceProvider = null; + INavigationRegionProvider? navigationRegionProvider = null; + IServiceFactory? serviceFactory = null; + IMessenger? messenger = null; + + if (resolvedRegion is null && region is not null) { if (args.Sender is IServiceProviderRequired requireServiceProvider) { - if (args.Scope is "self") + if (args.Scope is NavigateScope.Scoped) { - navigation = requireServiceProvider.Provider.GetRequiredService(); + serviceProvider = requireServiceProvider.Provider; + serviceFactory = requireServiceProvider.Provider.GetRequiredService(); + navigationRegionProvider = requireServiceProvider.Provider.GetRequiredService(); + messenger = requireServiceProvider.Provider.GetRequiredService(); } - if (args.Scope is "new") + if (args.Scope is NavigateScope.CreateScope) { IServiceScope serviceScope = requireServiceProvider.Provider.CreateScope(); - navigation = serviceScope.ServiceProvider.GetRequiredService(); + + serviceProvider = serviceScope.ServiceProvider; + serviceFactory = serviceScope.ServiceProvider.GetRequiredService(); + navigationRegionProvider = serviceScope.ServiceProvider.GetRequiredService(); + messenger = requireServiceProvider.Provider.GetRequiredService(); + } + + if (navigationRegionProvider is not null) + { + if (navigationRegionProvider.TryGet(region, out object? value)) + { + resolvedRegion = value; + } + } + } + + if (scopedServiceProvider.TryGet(scoped, out IServiceProvider? scopedProvider)) + { + serviceProvider ??= scopedProvider; + serviceFactory ??= scopedProvider?.GetRequiredService(); + messenger ??= scopedProvider?.GetRequiredService(); + + if (resolvedRegion is null) + { + + navigationRegionProvider = scopedProvider?.GetRequiredService(); + if (navigationRegionProvider is not null) + { + if (navigationRegionProvider.TryGet(region, out object? value)) + { + resolvedRegion = value; + } + } } } } - if (navigation is null) + if (resolvedRegion is not null && serviceProvider is not null && serviceFactory is not null && messenger is not null) { - ComponentScopeDescriptor? descriptor = componentScopeProvider.Get(args.Scope ?? named.Key); - navigation = descriptor?.Services?.GetRequiredService(); - } + Dictionary? arguments = parameters?.ToDictionary(x => x.Key, x => x.Value, StringComparer.InvariantCultureIgnoreCase) ?? []; - navigation?.Navigate(args.Route, args.Sender, - args.Region, args.Navigated, args.Parameters); + foreach (object segment in segments) + { + if (serviceProvider.GetRequiredKeyedService(segment) is IContentTemplateDescriptor descriptor) + { + if (serviceProvider.GetRequiredKeyedService(descriptor.TemplateType, descriptor.Key) is object template) + { + object?[] resolvedArguments = parameters is not null + ? descriptor.ContentType + .GetConstructors() + .FirstOrDefault()? + .GetParameters() + .Select(x => x?.Name is not null && arguments is not null && arguments.TryGetValue(x.Name, out object? argument) + ? argument + : null) + .Where(argument => argument is not null) + .ToArray() ?? [] : []; + + object? content = resolvedArguments is { Length: > 0 } + ? serviceFactory.Create(descriptor.ContentType, parameters) + : serviceProvider.GetRequiredKeyedService(descriptor.ContentType, descriptor.Key); + + messenger.Send(new NavigateTemplateEventArgs(resolvedRegion, template, content, sender, parameters), + resolvedRegion is string ? $"{resolvedRegion}" : resolvedRegion.GetType().Name); + } + } + } + } } } \ No newline at end of file diff --git a/Toolkit.Foundation/NavigateScope.cs b/Toolkit.Foundation/NavigateScope.cs new file mode 100644 index 0000000..5bb4e9d --- /dev/null +++ b/Toolkit.Foundation/NavigateScope.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public enum NavigateScope +{ + Default, + Scoped, + CreateScope +} diff --git a/Toolkit.Foundation/Navigation.cs b/Toolkit.Foundation/Navigation.cs index 3df4ea2..6ae5ceb 100644 --- a/Toolkit.Foundation/Navigation.cs +++ b/Toolkit.Foundation/Navigation.cs @@ -1,86 +1,11 @@ using CommunityToolkit.Mvvm.Messaging; -using Microsoft.Extensions.DependencyInjection; namespace Toolkit.Foundation; -public class Navigation(IServiceProvider provider, - INavigationRegionProvider navigationRegionProvider, - IContentFactory contentFactory, +public class Navigation(INavigationRegionProvider navigationRegionProvider, IMessenger messenger) : INavigation { - public void Navigate(string route, - object? sender = null, - object? region = null, - EventHandler? navigated = null, - IDictionary? parameters = null) - { - if (region is null) - { - return; - } - - string[] segments = route.Split('/'); - int segmentCount = segments.Length; - int currentSegmentIndex = 0; - - foreach (object segment in segments) - { - currentSegmentIndex++; - - if (provider.GetRequiredKeyedService(segment) - is IContentTemplateDescriptor descriptor) - { - Dictionary? arguments = parameters?.ToDictionary(x => x.Key, x => x.Value, StringComparer.InvariantCultureIgnoreCase) ?? []; - object?[] resolvedArguments = parameters is not null - ? descriptor.ContentType - .GetConstructors() - .FirstOrDefault()? - .GetParameters() - .Select(x => x?.Name is not null && arguments is not null && arguments.TryGetValue(x.Name, out object? argument) - ? argument - : null) - .Where(argument => argument is not null) - .ToArray() ?? [] : []; - - if (provider.GetRequiredKeyedService(descriptor.TemplateType, descriptor.Key) - is object template) - { - if (region is not null) - { - switch (region) - { - case "self": - region = template; - break; - - default: - if (navigationRegionProvider.TryGet(region, out object? value)) - { - region = value; - } - - break; - } - } - - if (region is not null) - { - object? content = contentFactory.Create(descriptor, resolvedArguments); - if (content is not null) - { - messenger.Send(new NavigateTemplateEventArgs(region, template, content, sender, parameters), region is string ? $"{region}" : region.GetType().Name); - if (currentSegmentIndex == segmentCount) - { - navigated?.Invoke(this, EventArgs.Empty); - } - } - } - } - } - } - } - public void Back(object? region) { if (region is not null) diff --git a/Toolkit.Foundation/NotificationAttribute.cs b/Toolkit.Foundation/NotificationAttribute.cs deleted file mode 100644 index 00c7d47..0000000 --- a/Toolkit.Foundation/NotificationAttribute.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Toolkit.Foundation; - -[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] -public class NotificationAttribute(Type type, - object key) : Attribute -{ - public Type Type => type; - - public object Key => key; -} \ No newline at end of file diff --git a/Toolkit.Foundation/ObjectExtensions.cs b/Toolkit.Foundation/ObjectExtensions.cs index 3ffcf4c..96a432f 100644 --- a/Toolkit.Foundation/ObjectExtensions.cs +++ b/Toolkit.Foundation/ObjectExtensions.cs @@ -4,17 +4,10 @@ namespace Toolkit.Foundation; public static class ObjectExtensions { - public static object? GetPropertyValue(this object obj, Func selector) + public static T Also(this T value, Action action) { - Type type = obj.GetType(); - - object? key = selector(); - if (type.GetProperty($"{key}") is PropertyInfo property && property.GetValue(obj) is { } value) - { - return value; - } - - return null; + action(value); + return value; } public static TAttribute? GetAttribute(this object obj) @@ -40,4 +33,17 @@ public static class ObjectExtensions return Enumerable.Empty(); } + + public static object? GetPropertyValue(this object obj, Func selector) + { + Type type = obj.GetType(); + + object? key = selector(); + if (type.GetProperty($"{key}") is PropertyInfo property && property.GetValue(obj) is { } value) + { + return value; + } + + return null; + } } \ No newline at end of file diff --git a/Toolkit.Foundation/Observable.cs b/Toolkit.Foundation/Observable.cs index 301005e..b56e265 100644 --- a/Toolkit.Foundation/Observable.cs +++ b/Toolkit.Foundation/Observable.cs @@ -95,11 +95,18 @@ public partial class Observable : Value = value; } - protected virtual void Changed(TValue? value) + protected virtual void ValueChanged(TValue? value) { } - partial void OnValueChanged(TValue? value) => Changed(value); + protected virtual void ValueChanged(TValue? oldValue, TValue? newValue) + { + + } + + partial void OnValueChanged(TValue? value) => ValueChanged(value); + + partial void OnValueChanged(TValue? oldValue, TValue? newValue) => ValueChanged(oldValue, newValue); } public partial class Observable : @@ -122,9 +129,16 @@ public partial class Observable : Value = value; } - protected virtual void ValueChanged() + protected virtual void ValueChanged(TValue? value) { } - partial void OnValueChanged(TValue? value) => ValueChanged(); + protected virtual void ValueChanged(TValue? oldValue, TValue? newValue) + { + + } + + partial void OnValueChanged(TValue? value) => ValueChanged(value); + + partial void OnValueChanged(TValue? oldValue, TValue? newValue) => ValueChanged(oldValue, newValue); } diff --git a/Toolkit.Foundation/ObservableCollection.cs b/Toolkit.Foundation/ObservableCollection.cs index 5c4f248..f053f33 100644 --- a/Toolkit.Foundation/ObservableCollection.cs +++ b/Toolkit.Foundation/ObservableCollection.cs @@ -662,11 +662,18 @@ public partial class ObservableCollection : Value = value; } - protected virtual void Changed(TValue? value) + protected virtual void ValueChanged(TValue? value) { } - partial void OnValueChanged(TValue? value) => Changed(value); + protected virtual void ValueChanged(TValue? oldValue, TValue? newValue) + { + + } + + partial void OnValueChanged(TValue? value) => ValueChanged(value); + + partial void OnValueChanged(TValue? oldValue, TValue? newValue) => ValueChanged(oldValue, newValue); } public partial class ObservableCollection : @@ -701,6 +708,19 @@ public partial class ObservableCollection : Key = key; Value = value; } + + protected virtual void ValueChanged(TValue? value) + { + } + + protected virtual void ValueChanged(TValue? oldValue, TValue? newValue) + { + + } + + partial void OnValueChanged(TValue? value) => ValueChanged(value); + + partial void OnValueChanged(TValue? oldValue, TValue? newValue) => ValueChanged(oldValue, newValue); } public class ObservableCollection : diff --git a/Toolkit.Foundation/ObservableConfiguration.cs b/Toolkit.Foundation/ObservableConfiguration.cs index 547e7f3..3d5cf03 100644 --- a/Toolkit.Foundation/ObservableConfiguration.cs +++ b/Toolkit.Foundation/ObservableConfiguration.cs @@ -42,13 +42,13 @@ public partial class ObservableConfiguration : protected override void Activated() => dispatcher.Invoke(() => Value = read(configuration)); - protected override void Changed(TValue? value) + protected override void ValueChanged(TValue? value) { if (IsActive) { writer.Write(args => write(value, args)); } - base.Changed(value); + base.ValueChanged(value); } } \ No newline at end of file diff --git a/Toolkit.Foundation/ObservableConfigurationCollection.cs b/Toolkit.Foundation/ObservableConfigurationCollection.cs index 7c188ef..1b79aba 100644 --- a/Toolkit.Foundation/ObservableConfigurationCollection.cs +++ b/Toolkit.Foundation/ObservableConfigurationCollection.cs @@ -65,13 +65,13 @@ public partial class ObservableConfigurationCollection dispatcher.Invoke(() => Value = read(configuration)); - protected override void Changed(TValue? value) + protected override void ValueChanged(TValue? value) { if (IsActive) { writer.Write(args => write(value, args)); } - base.Changed(value); + base.ValueChanged(value); } } diff --git a/Toolkit.Foundation/NamedComponent.cs b/Toolkit.Foundation/Scoped.cs similarity index 66% rename from Toolkit.Foundation/NamedComponent.cs rename to Toolkit.Foundation/Scoped.cs index 82c401c..bc3d32c 100644 --- a/Toolkit.Foundation/NamedComponent.cs +++ b/Toolkit.Foundation/Scoped.cs @@ -1,6 +1,6 @@ namespace Toolkit.Foundation; -public record NamedComponent(string Key) +public record Scoped(string Key) { public override string ToString() => Key; } \ No newline at end of file diff --git a/Toolkit.Foundation/ScopedServiceFactory.cs b/Toolkit.Foundation/ScopedServiceFactory.cs index 8a90d4b..b233df7 100644 --- a/Toolkit.Foundation/ScopedServiceFactory.cs +++ b/Toolkit.Foundation/ScopedServiceFactory.cs @@ -3,11 +3,11 @@ namespace Toolkit.Foundation; public class ScopedServiceFactory(IServiceScopeFactory serviceScopeFactory, - ICache cache) : + ICache cache) : IScopedServiceFactory where TScopedService : notnull { - public (IServiceScope, TScopedService) Create(params object?[] parameters) + public (IServiceProvider, TScopedService) Create(params object?[] parameters) { if (serviceScopeFactory.CreateScope() is IServiceScope serviceScope) { @@ -18,14 +18,14 @@ public class ScopedServiceFactory(IServiceScopeFactory serviceSc if (factory.Create(parameters) is TScopedService service) { serviceProvider.GetRequiredService>().Set(service); - cache.Add(service, serviceScope); + cache.Add(service, serviceProvider); - foreach (IInitializationScoped initializationScoped in serviceScope.ServiceProvider.GetServices()) + foreach (IInitializationScoped initializationScoped in serviceProvider.GetServices()) { initializationScoped.Initialize(); } - return (serviceScope, service); + return (serviceProvider, service); } } } diff --git a/Toolkit.Foundation/ScopedServiceProvider.cs b/Toolkit.Foundation/ScopedServiceProvider.cs index 445cd78..20a5677 100644 --- a/Toolkit.Foundation/ScopedServiceProvider.cs +++ b/Toolkit.Foundation/ScopedServiceProvider.cs @@ -1,21 +1,19 @@ -using Microsoft.Extensions.DependencyInjection; +namespace Toolkit.Foundation; -namespace Toolkit.Foundation; - -public class ScopedServiceProvider(ICache cache) : +public class ScopedServiceProvider(ICache cache) : IScopedServiceProvider where TService : notnull { public bool TryGet(TService service, - out IServiceScope? serviceScope) + out IServiceProvider? serviceProvider) { - if (cache.TryGetValue(service, out IServiceScope? value)) + if (cache.TryGetValue(service, out IServiceProvider? value)) { - serviceScope = value; + serviceProvider = value; return true; } - serviceScope = null; + serviceProvider = null; return false; } } \ No newline at end of file diff --git a/Toolkit.UI.Avalonia/NavigateAction.cs b/Toolkit.UI.Avalonia/NavigateAction.cs index 3b46966..731baad 100644 --- a/Toolkit.UI.Avalonia/NavigateAction.cs +++ b/Toolkit.UI.Avalonia/NavigateAction.cs @@ -22,13 +22,11 @@ public class NavigateAction : public static readonly StyledProperty RouteProperty = AvaloniaProperty.Register(nameof(Route)); - public static readonly StyledProperty ScopeProperty = - AvaloniaProperty.Register(nameof(Scope)); + public static readonly StyledProperty ScopeProperty = + AvaloniaProperty.Register(nameof(Scope)); private ParameterCollection parameterCollection = []; - public event EventHandler? Navigated; - public object Region { get => GetValue(RegionProperty); @@ -45,7 +43,7 @@ public class NavigateAction : set => SetValue(RouteProperty, value); } - public string Scope + public NavigateScope? Scope { get => GetValue(ScopeProperty); set => SetValue(ScopeProperty, value); @@ -65,7 +63,7 @@ public class NavigateAction : ImmutableDictionary.Empty; observableViewModel.Messenger.Send(new NavigateEventArgs(Route, Region == this ? content : Region, Scope ?? null, - content.DataContext, Navigated, parameters)); + content.DataContext, parameters)); } } diff --git a/Toolkit.UI.WinUI/ItemContainerInvokedBehavior.cs b/Toolkit.UI.WinUI/ItemContainerInvokedBehavior.cs index 66a0a12..49aa62f 100644 --- a/Toolkit.UI.WinUI/ItemContainerInvokedBehavior.cs +++ b/Toolkit.UI.WinUI/ItemContainerInvokedBehavior.cs @@ -1,5 +1,4 @@ using Microsoft.UI.Xaml; -using System; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; using Microsoft.Xaml.Interactivity; diff --git a/Toolkit.UI.WinUI/MediaPlayerBehavior.cs b/Toolkit.UI.WinUI/MediaPlayerBehavior.cs new file mode 100644 index 0000000..1becc6b --- /dev/null +++ b/Toolkit.UI.WinUI/MediaPlayerBehavior.cs @@ -0,0 +1,47 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.Xaml.Interactivity; +using Windows.Media.Playback; + +namespace Toolkit.UI.WinUI; + +public class MediaPlayerBehavior : + Behavior +{ + public static readonly DependencyProperty MediaPlayerProperty = + DependencyProperty.Register(nameof(MediaPlayer), + typeof(MediaPlayer), typeof(MediaPlayerBehavior), + new PropertyMetadata(null, OnMediaPlayerPropertyChanged)); + + public MediaPlayer MediaPlayer + { + get => (MediaPlayer)GetValue(MediaPlayerProperty); + set => SetValue(MediaPlayerProperty, value); + } + + private static void OnMediaPlayerPropertyChanged(DependencyObject dependencyObject, + DependencyPropertyChangedEventArgs args) + { + if (dependencyObject is MediaPlayerBehavior behavior) + { + behavior.OnMediaPlayerPropertyChanged(); + } + } + + private void OnMediaPlayerPropertyChanged() => + SetMediaPlayer(); + + private void SetMediaPlayer() + { + if (MediaPlayer is not null && AssociatedObject is not null) + { + AssociatedObject.SetMediaPlayer(MediaPlayer); + } + } + + protected override void OnAttached() + { + base.OnAttached(); + SetMediaPlayer(); + } +} diff --git a/Toolkit.UI.WinUI/NavigateAction.cs b/Toolkit.UI.WinUI/NavigateAction.cs index e05d488..0733a75 100644 --- a/Toolkit.UI.WinUI/NavigateAction.cs +++ b/Toolkit.UI.WinUI/NavigateAction.cs @@ -28,8 +28,8 @@ public class NavigateAction : public static readonly DependencyProperty ScopeProperty = DependencyProperty.Register(nameof(Scope), - typeof(string), typeof(NavigateAction), - new PropertyMetadata(null)); + typeof(NavigateScope), typeof(NavigateAction), + new PropertyMetadata(NavigateScope.Default)); public static readonly DependencyProperty ParametersProperty = DependencyProperty.Register(nameof(Parameters), @@ -38,8 +38,6 @@ public class NavigateAction : private ParameterCollection parameterCollection = []; - public event EventHandler? Navigated; - public object Region { get => GetValue(RegionProperty); @@ -55,9 +53,9 @@ public class NavigateAction : set => SetValue(RouteProperty, value); } - public string Scope + public NavigateScope Scope { - get => (string)GetValue(ScopeProperty); + get => (NavigateScope)GetValue(ScopeProperty); set => SetValue(ScopeProperty, value); } @@ -74,8 +72,8 @@ public class NavigateAction : ImmutableDictionary? parameters = Parameters is { Count: > 0 } ? Parameters.ToImmutableDictionary(x => x.Key, x => x.Value) : ImmutableDictionary.Empty; - observableViewModel.Messenger.Send(new NavigateEventArgs(Route, Region.Equals(this) ? content : Region, Scope ?? null, - content.DataContext, Navigated, parameters)); + observableViewModel.Messenger.Send(new NavigateEventArgs(Route, Region.Equals(this) ? content : Region, Scope, + content.DataContext, parameters)); } }