wip
This commit is contained in:
@@ -37,6 +37,7 @@ public class AsyncHandlerInitialization<TMessage, THandler>(IServiceProvider pro
|
|||||||
foreach (IAsyncHandler<TMessage> handler in provider.GetServices<IAsyncHandler<TMessage>>())
|
foreach (IAsyncHandler<TMessage> handler in provider.GetServices<IAsyncHandler<TMessage>>())
|
||||||
{
|
{
|
||||||
handler.Handle(args.Message, args.CancellationToken);
|
handler.Handle(args.Message, args.CancellationToken);
|
||||||
|
args.Reply(Unit.Value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,4 +34,12 @@ public static class IMessengerExtensions
|
|||||||
public static async Task<TResponse> SendAsync<TMessage, TResponse>(this IMessenger messenger,
|
public static async Task<TResponse> SendAsync<TMessage, TResponse>(this IMessenger messenger,
|
||||||
TMessage message) where TMessage : class =>
|
TMessage message) where TMessage : class =>
|
||||||
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = message });
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = message });
|
||||||
|
|
||||||
|
public static async Task SendAsync<TMessage>(this IMessenger messenger)
|
||||||
|
where TMessage : class, new() =>
|
||||||
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, Unit> { Message = new TMessage() });
|
||||||
|
|
||||||
|
public static async Task SendAsync<TMessage>(this IMessenger messenger,
|
||||||
|
TMessage message) where TMessage : class =>
|
||||||
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, Unit> { Message = message });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ public static class IServiceCollectionExtensions
|
|||||||
if (key is { Length: > 0 })
|
if (key is { Length: > 0 })
|
||||||
{
|
{
|
||||||
services.Add(new ServiceDescriptor(typeof(IAsyncHandler<TMessage>), key, typeof(THandler), lifetime));
|
services.Add(new ServiceDescriptor(typeof(IAsyncHandler<TMessage>), key, typeof(THandler), lifetime));
|
||||||
services.AddInitialization<AsyncHandlerInitialization<TMessage, IAsyncHandler<TMessage>>>(key);
|
services.AddInitialization<AsyncHandlerKeyedInitialization<TMessage, IAsyncHandler<TMessage>>>(key);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
services.Add(new ServiceDescriptor(typeof(IAsyncHandler<TMessage>), typeof(THandler), lifetime));
|
services.Add(new ServiceDescriptor(typeof(IAsyncHandler<TMessage>), typeof(THandler), lifetime));
|
||||||
services.AddInitialization<AsyncHandlerKeyedInitialization<TMessage, IAsyncHandler<TMessage>>>();
|
services.AddInitialization<AsyncHandlerInitialization<TMessage, IAsyncHandler<TMessage>>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
|
|||||||
@@ -67,13 +67,15 @@ public partial class Observable(IServiceProvider provider,
|
|||||||
|
|
||||||
protected override sealed void OnActivated()
|
protected override sealed void OnActivated()
|
||||||
{
|
{
|
||||||
base.OnActivated();
|
Messenger.RegisterAll(this);
|
||||||
Activated();
|
Activated();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override sealed void OnDeactivated()
|
protected override sealed void OnDeactivated()
|
||||||
{
|
{
|
||||||
base.OnDeactivated();
|
Messenger.UnregisterAll(this);
|
||||||
|
Dispose();
|
||||||
|
|
||||||
Deactivated();
|
Deactivated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
|
||||||
namespace Toolkit.Foundation;
|
namespace Toolkit.Foundation;
|
||||||
@@ -38,8 +36,6 @@ public abstract partial class ObservableCollection<TViewModel> :
|
|||||||
|
|
||||||
private readonly Dictionary<string, object> trackedProperties = [];
|
private readonly Dictionary<string, object> trackedProperties = [];
|
||||||
|
|
||||||
private bool cleaning;
|
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private int count;
|
private int count;
|
||||||
|
|
||||||
@@ -173,7 +169,6 @@ public abstract partial class ObservableCollection<TViewModel> :
|
|||||||
|
|
||||||
public void Clear(bool disposeItems = false)
|
public void Clear(bool disposeItems = false)
|
||||||
{
|
{
|
||||||
cleaning = true;
|
|
||||||
if (disposeItems)
|
if (disposeItems)
|
||||||
{
|
{
|
||||||
foreach (TViewModel item in this.ToList())
|
foreach (TViewModel item in this.ToList())
|
||||||
@@ -184,12 +179,10 @@ public abstract partial class ObservableCollection<TViewModel> :
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClearItems();
|
ClearItems();
|
||||||
cleaning = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
cleaning = true;
|
|
||||||
foreach (TViewModel item in this.ToList())
|
foreach (TViewModel item in this.ToList())
|
||||||
{
|
{
|
||||||
Disposer.Dispose(item);
|
Disposer.Dispose(item);
|
||||||
@@ -197,7 +190,6 @@ public abstract partial class ObservableCollection<TViewModel> :
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClearItems();
|
ClearItems();
|
||||||
cleaning = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Commit()
|
public void Commit()
|
||||||
@@ -222,8 +214,8 @@ public abstract partial class ObservableCollection<TViewModel> :
|
|||||||
|
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
Disposer.Dispose(this);
|
Disposer.Dispose(this);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<TViewModel> GetEnumerator() =>
|
public IEnumerator<TViewModel> GetEnumerator() =>
|
||||||
@@ -471,7 +463,7 @@ public abstract partial class ObservableCollection<TViewModel> :
|
|||||||
Disposer.Add(this, item);
|
Disposer.Add(this, item);
|
||||||
Disposer.Add(item, Disposable.Create(() =>
|
Disposer.Add(item, Disposable.Create(() =>
|
||||||
{
|
{
|
||||||
if (item is IDisposable && !cleaning)
|
if (item is IDisposable)
|
||||||
{
|
{
|
||||||
if (item is IList collection)
|
if (item is IList collection)
|
||||||
{
|
{
|
||||||
@@ -487,13 +479,15 @@ public abstract partial class ObservableCollection<TViewModel> :
|
|||||||
|
|
||||||
protected override sealed void OnActivated()
|
protected override sealed void OnActivated()
|
||||||
{
|
{
|
||||||
base.OnActivated();
|
Messenger.RegisterAll(this);
|
||||||
Activated();
|
Activated();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override sealed void OnDeactivated()
|
protected override sealed void OnDeactivated()
|
||||||
{
|
{
|
||||||
base.OnDeactivated();
|
Messenger.UnregisterAll(this);
|
||||||
|
Dispose();
|
||||||
|
|
||||||
Deactivated();
|
Deactivated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,4 +7,4 @@ public record Update
|
|||||||
|
|
||||||
public static UpdateEventArgs<TValue> As<TValue>() where TValue : new() =>
|
public static UpdateEventArgs<TValue> As<TValue>() where TValue : new() =>
|
||||||
new(new TValue());
|
new(new TValue());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ public record UpdateEventArgs<TSender>
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record Updated
|
||||||
|
{
|
||||||
|
public static UpdatedEventArgs<TValue> As<TValue>(TValue value) =>
|
||||||
|
new(value);
|
||||||
|
|
||||||
|
public static UpdatedEventArgs<TValue> As<TValue>() where TValue : new() =>
|
||||||
|
new(new TValue());
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record UpdatedEventArgs<TSender>
|
||||||
|
{
|
||||||
|
public TSender? Sender { get; }
|
||||||
|
|
||||||
|
public UpdatedEventArgs(TSender sender)
|
||||||
|
{
|
||||||
|
Sender = sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdatedEventArgs()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,21 +23,33 @@ public static class ContentTemplateBinding
|
|||||||
{
|
{
|
||||||
if (dependencyObject is FrameworkElement content)
|
if (dependencyObject is FrameworkElement content)
|
||||||
{
|
{
|
||||||
|
IActivation? cachedActivation = null;
|
||||||
|
|
||||||
void HandleLoaded(object sender, RoutedEventArgs args)
|
void HandleLoaded(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (content.DataContext is IActivation activation)
|
if (sender is FrameworkElement content)
|
||||||
{
|
{
|
||||||
content.Loaded -= HandleLoaded;
|
content.Loaded -= HandleLoaded;
|
||||||
activation.IsActive = true;
|
|
||||||
|
if (content.DataContext is IActivation activation)
|
||||||
|
{
|
||||||
|
cachedActivation = activation;
|
||||||
|
activation.IsActive = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleUnloaded(object sender, RoutedEventArgs args)
|
void HandleUnloaded(object sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
if (content.DataContext is IActivation activation)
|
if (cachedActivation is not null)
|
||||||
{
|
{
|
||||||
|
cachedActivation.IsActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sender is FrameworkElement content)
|
||||||
|
{
|
||||||
|
cachedActivation = null;
|
||||||
content.Unloaded -= HandleUnloaded;
|
content.Unloaded -= HandleUnloaded;
|
||||||
activation.IsActive = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +57,6 @@ public static class ContentTemplateBinding
|
|||||||
{
|
{
|
||||||
content.Loaded += HandleLoaded;
|
content.Loaded += HandleLoaded;
|
||||||
content.Unloaded += HandleUnloaded;
|
content.Unloaded += HandleUnloaded;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.WinUI;
|
||||||
|
|
||||||
|
public class StringFormatConverter :
|
||||||
|
ValueConverter<object, object>
|
||||||
|
{
|
||||||
|
public string? StringFormat { get; set; }
|
||||||
|
|
||||||
|
protected override object? ConvertTo(object value,
|
||||||
|
Type? targetType,
|
||||||
|
object? parameter,
|
||||||
|
string? language)
|
||||||
|
{
|
||||||
|
if (value is null)
|
||||||
|
{
|
||||||
|
return null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(StringFormat))
|
||||||
|
{
|
||||||
|
return value.ToString()!;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CultureInfo culture = string.IsNullOrWhiteSpace(language) ? CultureInfo.InvariantCulture : new CultureInfo(language);
|
||||||
|
return string.Format(culture, StringFormat, value);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
using Microsoft.UI.Xaml.Markup;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.WinUI;
|
||||||
|
|
||||||
|
public abstract class ValueConverter<TSource, TTarget> :
|
||||||
|
MarkupExtension,
|
||||||
|
IValueConverter
|
||||||
|
{
|
||||||
|
public object? Convert(object value,
|
||||||
|
Type targetType,
|
||||||
|
object parameter,
|
||||||
|
string language) =>
|
||||||
|
ConvertTo((TSource)value, targetType, parameter, language);
|
||||||
|
|
||||||
|
public object? ConvertBack(object value,
|
||||||
|
Type targetType,
|
||||||
|
object parameter,
|
||||||
|
string language) =>
|
||||||
|
ConvertBackTo((TTarget)value, targetType, parameter, language);
|
||||||
|
|
||||||
|
public TTarget? Convert(TSource value) =>
|
||||||
|
ConvertTo(value, null, null, null);
|
||||||
|
|
||||||
|
public TSource? ConvertBack(TTarget value) =>
|
||||||
|
ConvertBackTo(value, null, null, null);
|
||||||
|
|
||||||
|
protected virtual TTarget? ConvertTo(TSource value,
|
||||||
|
Type? targetType,
|
||||||
|
object? parameter,
|
||||||
|
string? language) => default;
|
||||||
|
|
||||||
|
protected virtual TSource? ConvertBackTo(TTarget value,
|
||||||
|
Type? targetType,
|
||||||
|
object? parameter,
|
||||||
|
string? language) => default;
|
||||||
|
|
||||||
|
protected override object ProvideValue() => this;
|
||||||
|
}
|
||||||
@@ -40,11 +40,6 @@ public class ContentControlHandler :
|
|||||||
{
|
{
|
||||||
activation.IsActive = false;
|
activation.IsActive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content is IDisposable disposable)
|
|
||||||
{
|
|
||||||
disposable.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.UI.Dispatching;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Toolkit.Foundation;
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ public static class IServiceCollectionExtensions
|
|||||||
{
|
{
|
||||||
public static IServiceCollection AddWinUI(this IServiceCollection services)
|
public static IServiceCollection AddWinUI(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddTransient<IDispatcher, WinUIDispatcher>();
|
services.AddSingleton<IDispatcher>(provider => new WinUIDispatcher(DispatcherQueue.GetForCurrentThread()));
|
||||||
services.AddTransient<IDispatcherTimerFactory, DispatcherTimerFactory>();
|
services.AddTransient<IDispatcherTimerFactory, DispatcherTimerFactory>();
|
||||||
services.AddSingleton<IWindowRegistry, WindowRegistry>();
|
services.AddSingleton<IWindowRegistry, WindowRegistry>();
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ using Toolkit.Foundation;
|
|||||||
|
|
||||||
namespace Toolkit.WinUI;
|
namespace Toolkit.WinUI;
|
||||||
|
|
||||||
public class WinUIDispatcher :
|
public class WinUIDispatcher(DispatcherQueue dispatcherQueue) :
|
||||||
IDispatcher
|
IDispatcher
|
||||||
{
|
{
|
||||||
public Task Invoke(Action action)
|
public Task Invoke(Action action)
|
||||||
{
|
{
|
||||||
DispatcherQueue.GetForCurrentThread().TryEnqueue(action.Invoke);
|
dispatcherQueue.TryEnqueue(action.Invoke);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user