Fix region bug
This commit is contained in:
@@ -47,7 +47,7 @@ public class ComponentFactory(IServiceProvider provider,
|
||||
provider.GetRequiredService<IComponentScopeProvider>());
|
||||
|
||||
services.AddRange(proxy.Services);
|
||||
services.AddSingleton(new NamedComponent(key));
|
||||
services.AddSingleton(new Scoped(key));
|
||||
|
||||
if (servicesDelegate is not null)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ public class ComponentInitializer(IEnumerable<IComponent> components,
|
||||
|
||||
services.AddRange(typedServices.Services);
|
||||
|
||||
services.AddSingleton(new NamedComponent(component.GetType().Name));
|
||||
services.AddSingleton(new Scoped(component.GetType().Name));
|
||||
});
|
||||
|
||||
IComponentHost host = builder.Build();
|
||||
|
||||
@@ -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<IContentFactory, ContentFactory>();
|
||||
|
||||
services.AddSingleton<INavigationRegionCollection, NavigationRegionCollection>();
|
||||
services.AddScoped<INavigationRegionCollection, NavigationRegionCollection>();
|
||||
services.AddTransient<INavigationRegionProvider, NavigationRegionProvider>();
|
||||
|
||||
services.AddScoped<INavigation, Navigation>();
|
||||
|
||||
services.AddSingleton(new NamedComponent("Root"));
|
||||
services.AddScoped<IComponentScopeCollection, ComponentScopeCollection>(provider =>
|
||||
[
|
||||
new ComponentScopeDescriptor("Root", provider.GetRequiredService<IServiceProvider>())
|
||||
]);
|
||||
services.AddTransient<IComparer<Scoped>>(provider => Comparer<Scoped>.Create((x, z) =>
|
||||
StringComparer.CurrentCultureIgnoreCase.Compare(x.Key, z.Key)));
|
||||
|
||||
services.AddTransient<IComponentFactory, ComponentFactory>();
|
||||
services.AddTransient<IComponentScopeProvider, ComponentScopeProvider>();
|
||||
Scoped named = new("Root");
|
||||
services.AddSingleton<IScopedServiceDescriptor<Scoped>>(provider =>
|
||||
{
|
||||
ScopedServiceDescriptor<Scoped> descriptor = new();
|
||||
descriptor.Set(named);
|
||||
|
||||
return descriptor;
|
||||
});
|
||||
|
||||
services.AddSingleton(provider => provider.GetRequiredService<IScopedServiceDescriptor<Scoped>>().Value!);
|
||||
|
||||
services.AddSingleton<ICache<Scoped, IServiceProvider>>(provider =>
|
||||
{
|
||||
Cache<Scoped, IServiceProvider> cache = new(provider.GetRequiredService<IComparer<Scoped>>())
|
||||
{
|
||||
{ named, provider }
|
||||
};
|
||||
|
||||
return cache;
|
||||
});
|
||||
|
||||
services.AddTransient(provider => provider.GetService<ICache<Scoped, IServiceProvider>>()!.Select(x => x.Value));
|
||||
|
||||
services.AddTransient<IScopedServiceProvider<Scoped>, ScopedServiceProvider<Scoped>>();
|
||||
services.AddTransient<IScopedServiceFactory<Scoped>, ScopedServiceFactory<Scoped>>();
|
||||
|
||||
//services.AddScoped<IComponentScopeCollection, ComponentScopeCollection>(provider =>
|
||||
//[
|
||||
// new ComponentScopeDescriptor("Root", provider.GetRequiredService<IServiceProvider>())
|
||||
//]);
|
||||
|
||||
//services.AddTransient<IComponentFactory, ComponentFactory>();
|
||||
//services.AddTransient<IComponentScopeProvider, ComponentScopeProvider>();
|
||||
|
||||
services.AddScopedHandler<NavigateEventArgs, NavigateHandler>();
|
||||
services.AddScopedHandler<NavigateBackEventArgs, NavigateBackHandler>();
|
||||
|
||||
services.AddTransient<IFileProvider, FileProvider>();
|
||||
|
||||
services.AddInitialization<ComponentInitializer>();
|
||||
//services.AddInitialization<ComponentInitializer>();
|
||||
});
|
||||
|
||||
builderDelegate.Invoke(hostBuilder);
|
||||
|
||||
@@ -2,11 +2,5 @@
|
||||
|
||||
public interface INavigation
|
||||
{
|
||||
void Navigate(string route,
|
||||
object? sender = null,
|
||||
object? region = null,
|
||||
EventHandler? navigated = null,
|
||||
IDictionary<string, object>? parameters = null);
|
||||
|
||||
void Back(object? region);
|
||||
}
|
||||
@@ -4,5 +4,5 @@ namespace Toolkit.Foundation;
|
||||
|
||||
public interface IScopedServiceFactory<TService>
|
||||
{
|
||||
(IServiceScope, TService) Create(params object?[] parameters);
|
||||
(IServiceProvider, TService) Create(params object?[] parameters);
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public interface IScopedServiceProvider<TService>
|
||||
{
|
||||
bool TryGet(TService service, out IServiceScope? serviceScope);
|
||||
bool TryGet(TService service, out IServiceProvider? serviceProvider);
|
||||
}
|
||||
@@ -50,11 +50,11 @@ public static class IServiceCollectionExtensions
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddAsyncHandlerScoped<TMessage, TResponse, THandler>(this IServiceCollection services,
|
||||
public static IServiceCollection AddScopedAsyncHandler<TMessage, TResponse, THandler>(this IServiceCollection services,
|
||||
string key) where THandler : class, IAsyncHandler<TMessage, TResponse>
|
||||
where TMessage : class => AddAsyncHandlerScoped<TMessage, TResponse, THandler>(services, ServiceLifetime.Transient, key);
|
||||
where TMessage : class => AddScopedAsyncHandler<TMessage, TResponse, THandler>(services, ServiceLifetime.Transient, key);
|
||||
|
||||
public static IServiceCollection AddAsyncHandlerScoped<TMessage, TResponse, THandler>(this IServiceCollection services,
|
||||
public static IServiceCollection AddScopedAsyncHandler<TMessage, TResponse, THandler>(this IServiceCollection services,
|
||||
ServiceLifetime lifetime = ServiceLifetime.Transient,
|
||||
string? key = null) where THandler : class, IAsyncHandler<TMessage, TResponse>
|
||||
where TMessage : class
|
||||
@@ -77,11 +77,11 @@ public static class IServiceCollectionExtensions
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddAsyncHandlerScoped<TMessage, THandler>(this IServiceCollection services,
|
||||
public static IServiceCollection AddScopedAsyncHandler<TMessage, THandler>(this IServiceCollection services,
|
||||
string key) where THandler : class, IAsyncHandler<TMessage>
|
||||
where TMessage : class => AddAsyncHandlerScoped<TMessage, THandler>(services, ServiceLifetime.Transient, key);
|
||||
where TMessage : class => AddScopedAsyncHandler<TMessage, THandler>(services, ServiceLifetime.Transient, key);
|
||||
|
||||
public static IServiceCollection AddAsyncHandlerScoped<TMessage, THandler>(this IServiceCollection services,
|
||||
public static IServiceCollection AddScopedAsyncHandler<TMessage, THandler>(this IServiceCollection services,
|
||||
ServiceLifetime lifetime = ServiceLifetime.Transient,
|
||||
string? key = null) where THandler : class, IAsyncHandler<TMessage>
|
||||
where TMessage : class
|
||||
@@ -357,7 +357,7 @@ public static class IServiceCollectionExtensions
|
||||
services.AddScoped<IScopedServiceDescriptor<TScopedService>, ScopedServiceDescriptor<TScopedService>>();
|
||||
services.AddScoped(provider => provider.GetRequiredService<IScopedServiceDescriptor<TScopedService>>().Value!);
|
||||
|
||||
services.AddCache<TScopedService, IServiceScope>();
|
||||
services.AddCache<TScopedService, IServiceProvider>();
|
||||
|
||||
services.AddTransient<IScopedServiceProvider<TScopedService>, ScopedServiceProvider<TScopedService>>();
|
||||
services.AddTransient<IScopedServiceFactory<TScopedService>, ScopedServiceFactory<TScopedService>>();
|
||||
@@ -372,7 +372,7 @@ public static class IServiceCollectionExtensions
|
||||
services.AddScoped<IScopedServiceDescriptor<TScopedService>, ScopedServiceDescriptor<TScopedService>>();
|
||||
services.AddScoped(provider => provider.GetRequiredService<IScopedServiceDescriptor<TScopedService>>().Value!);
|
||||
|
||||
services.AddCache<TScopedService, IServiceScope>();
|
||||
services.AddCache<TScopedService, IServiceProvider>();
|
||||
|
||||
services.AddTransient<IScopedServiceProvider<TScopedService>, ScopedServiceProvider<TScopedService>>();
|
||||
services.AddTransient<IScopedServiceFactory<TScopedService>, ScopedServiceFactory<TScopedService>>(provider =>
|
||||
@@ -380,7 +380,7 @@ public static class IServiceCollectionExtensions
|
||||
providerDelegate.Invoke(provider);
|
||||
|
||||
IServiceScopeFactory factory = provider.GetRequiredService<IServiceScopeFactory>();
|
||||
ICache<TScopedService, IServiceScope> cache = provider.GetRequiredService<ICache<TScopedService, IServiceScope>>();
|
||||
ICache<TScopedService, IServiceProvider> cache = provider.GetRequiredService<ICache<TScopedService, IServiceProvider>>();
|
||||
|
||||
return new ScopedServiceFactory<TScopedService>(factory, cache);
|
||||
});
|
||||
|
||||
@@ -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<string, object>? Parameters = null);
|
||||
|
||||
@@ -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<Scoped> scopedServiceProvider) :
|
||||
IHandler<NavigateEventArgs>
|
||||
{
|
||||
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<string, object>? 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<INavigation>();
|
||||
serviceProvider = requireServiceProvider.Provider;
|
||||
serviceFactory = requireServiceProvider.Provider.GetRequiredService<IServiceFactory>();
|
||||
navigationRegionProvider = requireServiceProvider.Provider.GetRequiredService<INavigationRegionProvider>();
|
||||
messenger = requireServiceProvider.Provider.GetRequiredService<IMessenger>();
|
||||
}
|
||||
|
||||
if (args.Scope is "new")
|
||||
if (args.Scope is NavigateScope.CreateScope)
|
||||
{
|
||||
IServiceScope serviceScope = requireServiceProvider.Provider.CreateScope();
|
||||
navigation = serviceScope.ServiceProvider.GetRequiredService<INavigation>();
|
||||
|
||||
serviceProvider = serviceScope.ServiceProvider;
|
||||
serviceFactory = serviceScope.ServiceProvider.GetRequiredService<IServiceFactory>();
|
||||
navigationRegionProvider = serviceScope.ServiceProvider.GetRequiredService<INavigationRegionProvider>();
|
||||
messenger = requireServiceProvider.Provider.GetRequiredService<IMessenger>();
|
||||
}
|
||||
|
||||
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<IServiceFactory>();
|
||||
messenger ??= scopedProvider?.GetRequiredService<IMessenger>();
|
||||
|
||||
if (resolvedRegion is null)
|
||||
{
|
||||
|
||||
navigationRegionProvider = scopedProvider?.GetRequiredService<INavigationRegionProvider>();
|
||||
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<INavigation>();
|
||||
}
|
||||
Dictionary<string, object>? 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<IContentTemplateDescriptor>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public enum NavigateScope
|
||||
{
|
||||
Default,
|
||||
Scoped,
|
||||
CreateScope
|
||||
}
|
||||
@@ -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<string, object>? 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<IContentTemplateDescriptor>(segment)
|
||||
is IContentTemplateDescriptor descriptor)
|
||||
{
|
||||
Dictionary<string, object>? 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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -4,17 +4,10 @@ namespace Toolkit.Foundation;
|
||||
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
public static object? GetPropertyValue(this object obj, Func<object> selector)
|
||||
public static T Also<T>(this T value, Action<T> 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<TAttribute>(this object obj)
|
||||
@@ -40,4 +33,17 @@ public static class ObjectExtensions
|
||||
|
||||
return Enumerable.Empty<TAttribute>();
|
||||
}
|
||||
|
||||
public static object? GetPropertyValue(this object obj, Func<object> selector)
|
||||
{
|
||||
Type type = obj.GetType();
|
||||
|
||||
object? key = selector();
|
||||
if (type.GetProperty($"{key}") is PropertyInfo property && property.GetValue(obj) is { } value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -95,11 +95,18 @@ public partial class Observable<TValue> :
|
||||
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<TKey, TValue> :
|
||||
@@ -122,9 +129,16 @@ public partial class Observable<TKey, TValue> :
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -662,11 +662,18 @@ public partial class ObservableCollection<TValue, TViewModel> :
|
||||
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<TKey, TValue, TViewModel> :
|
||||
@@ -701,6 +708,19 @@ public partial class ObservableCollection<TKey, TValue, TViewModel> :
|
||||
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 :
|
||||
|
||||
@@ -42,13 +42,13 @@ public partial class ObservableConfiguration<TConfiguration, TValue> :
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -65,13 +65,13 @@ public partial class ObservableConfigurationCollection<TConfiguration, TValue, T
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record NamedComponent(string Key)
|
||||
public record Scoped(string Key)
|
||||
{
|
||||
public override string ToString() => Key;
|
||||
}
|
||||
@@ -3,11 +3,11 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class ScopedServiceFactory<TScopedService>(IServiceScopeFactory serviceScopeFactory,
|
||||
ICache<TScopedService, IServiceScope> cache) :
|
||||
ICache<TScopedService, IServiceProvider> cache) :
|
||||
IScopedServiceFactory<TScopedService>
|
||||
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<TScopedService>(IServiceScopeFactory serviceSc
|
||||
if (factory.Create<TScopedService>(parameters) is TScopedService service)
|
||||
{
|
||||
serviceProvider.GetRequiredService<IScopedServiceDescriptor<TScopedService>>().Set(service);
|
||||
cache.Add(service, serviceScope);
|
||||
cache.Add(service, serviceProvider);
|
||||
|
||||
foreach (IInitializationScoped initializationScoped in serviceScope.ServiceProvider.GetServices<IInitializationScoped>())
|
||||
foreach (IInitializationScoped initializationScoped in serviceProvider.GetServices<IInitializationScoped>())
|
||||
{
|
||||
initializationScoped.Initialize();
|
||||
}
|
||||
|
||||
return (serviceScope, service);
|
||||
return (serviceProvider, service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class ScopedServiceProvider<TService>(ICache<TService, IServiceScope> cache) :
|
||||
public class ScopedServiceProvider<TService>(ICache<TService, IServiceProvider> cache) :
|
||||
IScopedServiceProvider<TService>
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,11 @@ public class NavigateAction :
|
||||
public static readonly StyledProperty<string> RouteProperty =
|
||||
AvaloniaProperty.Register<NavigateAction, string>(nameof(Route));
|
||||
|
||||
public static readonly StyledProperty<string> ScopeProperty =
|
||||
AvaloniaProperty.Register<NavigateAction, string>(nameof(Scope));
|
||||
public static readonly StyledProperty<NavigateScope?> ScopeProperty =
|
||||
AvaloniaProperty.Register<NavigateAction, NavigateScope?>(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<string, object>.Empty;
|
||||
|
||||
observableViewModel.Messenger.Send(new NavigateEventArgs(Route, Region == this ? content : Region, Scope ?? null,
|
||||
content.DataContext, Navigated, parameters));
|
||||
content.DataContext, parameters));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.Xaml.Interactivity;
|
||||
|
||||
@@ -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<MediaPlayerElement>
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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<string, object>? parameters = Parameters is { Count: > 0 } ? Parameters.ToImmutableDictionary(x => x.Key, x => x.Value) :
|
||||
ImmutableDictionary<string, object>.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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user