Fixed more edge cases
This commit is contained in:
@@ -54,7 +54,10 @@ public class ContentControlHandler :
|
||||
control.Unloaded += HandleUnloaded;
|
||||
|
||||
control.DataContext = args.Content;
|
||||
|
||||
contentControl.Content = null;
|
||||
contentControl.Content = control;
|
||||
|
||||
await taskCompletionSource.Task;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Immutable;
|
||||
using System.Reactive.Disposables;
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
@@ -10,6 +10,12 @@ public class Cache<TValue>(IDisposer disposer,
|
||||
{
|
||||
private readonly SortedSet<TValue> cache = new(comparer);
|
||||
|
||||
public int IndexOf(TValue value)
|
||||
{
|
||||
ImmutableSortedSet<TValue> hashSet = cache.ToImmutableSortedSet(comparer);
|
||||
return hashSet.IndexOf(value);
|
||||
}
|
||||
|
||||
public void Add(TValue value)
|
||||
{
|
||||
if (value is null)
|
||||
@@ -21,6 +27,17 @@ public class Cache<TValue>(IDisposer disposer,
|
||||
cache.Add(value);
|
||||
}
|
||||
|
||||
public bool TryGetValue(TValue key, out TValue? value)
|
||||
{
|
||||
if (cache.TryGetValue(key, out value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Clear() => cache.Clear();
|
||||
|
||||
public IEnumerator<TValue> GetEnumerator() => cache.GetEnumerator();
|
||||
@@ -30,14 +47,15 @@ public class Cache<TValue>(IDisposer disposer,
|
||||
public bool Remove(TValue value) => cache.Remove(value);
|
||||
}
|
||||
|
||||
public class Cache<TKey, TValue> :
|
||||
public class Cache<TKey, TValue>(IDisposer disposer,
|
||||
IComparer<TKey> comparer) :
|
||||
ICache<TKey, TValue>
|
||||
where TKey :
|
||||
notnull
|
||||
where TValue :
|
||||
notnull
|
||||
{
|
||||
private readonly ConcurrentDictionary<TKey, TValue> cache = new();
|
||||
private readonly SortedList<TKey, TValue> cache = new(comparer);
|
||||
|
||||
public void Add(TKey key,
|
||||
TValue value)
|
||||
@@ -49,6 +67,8 @@ public class Cache<TKey, TValue> :
|
||||
|
||||
public bool ContainsKey(TKey key) => cache.ContainsKey(key);
|
||||
|
||||
public int IndexOf(TKey key) => cache.IndexOfKey(key);
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => cache.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record Created
|
||||
{
|
||||
public static CreatedEventArgs<TValue> As<TValue>(TValue value) =>
|
||||
new(value);
|
||||
|
||||
public static CreatedEventArgs<TValue> As<TValue>() where TValue : new() =>
|
||||
new(new TValue());
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record CreatedEventArgs<TValue>(TValue Value);
|
||||
@@ -7,7 +7,11 @@ public interface ICache<TValue> :
|
||||
|
||||
void Clear();
|
||||
|
||||
int IndexOf(TValue value);
|
||||
|
||||
bool Remove(TValue value);
|
||||
|
||||
bool TryGetValue(TValue key, out TValue? value);
|
||||
}
|
||||
|
||||
public interface ICache<TKey, TValue> :
|
||||
@@ -17,13 +21,14 @@ public interface ICache<TKey, TValue> :
|
||||
where TValue :
|
||||
notnull
|
||||
{
|
||||
void Add(TKey key,
|
||||
TValue value);
|
||||
void Add(TKey key, TValue value);
|
||||
|
||||
void Clear();
|
||||
|
||||
bool ContainsKey(TKey key);
|
||||
|
||||
int IndexOf(TKey key);
|
||||
|
||||
bool Remove(TKey key);
|
||||
|
||||
bool TryGetValue(TKey key, out TValue? value);
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.FileProviders.Physical;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record Modified
|
||||
{
|
||||
public static ModifiedEventArgs<TValue> As<TValue>(TValue oldValue, TValue newValue) =>
|
||||
new(oldValue, newValue);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record ModifiedEventArgs<TValue>(TValue OldView, TValue NewValue);
|
||||
@@ -8,12 +8,25 @@ public class NavigateHandler(NamedComponent scope,
|
||||
{
|
||||
public Task Handle(NavigateEventArgs args)
|
||||
{
|
||||
INavigationScope? navigationScope;
|
||||
if (args.Scope == "self" && args.Sender is IServiceProviderRequired requireServiceProvider)
|
||||
INavigationScope? navigationScope = null;
|
||||
if (args.Scope is "self" || args.Scope is "new")
|
||||
{
|
||||
navigationScope = requireServiceProvider.Provider.GetRequiredService<INavigationScope>();
|
||||
if (args.Sender is IServiceProviderRequired requireServiceProvider)
|
||||
{
|
||||
if (args.Scope is "self")
|
||||
{
|
||||
navigationScope = requireServiceProvider.Provider.GetRequiredService<INavigationScope>();
|
||||
}
|
||||
|
||||
if (args.Scope is "new")
|
||||
{
|
||||
IServiceScope serviceScope = requireServiceProvider.Provider.CreateScope();
|
||||
navigationScope = serviceScope.ServiceProvider.GetRequiredService<INavigationScope>();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (navigationScope is null)
|
||||
{
|
||||
ComponentScopeDescriptor? descriptor = componentScopeProvider.Get(args.Scope ?? scope.Name);
|
||||
navigationScope = descriptor?.Services?.GetRequiredService<INavigationScope>();
|
||||
|
||||
@@ -63,7 +63,7 @@ public partial class Observable :
|
||||
public virtual Task OnDeactivating() =>
|
||||
Task.CompletedTask;
|
||||
|
||||
public void Dispose()
|
||||
public virtual void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
Disposer.Dispose(this);
|
||||
|
||||
@@ -24,12 +24,14 @@ public partial class ObservableCollection<TItem> :
|
||||
IPublisherRequired,
|
||||
IDisposerRequired,
|
||||
INotificationHandler<RemoveEventArgs<TItem>>,
|
||||
INotificationHandler<RemoveAtEventArgs<TItem>>,
|
||||
INotificationHandler<RemoveAndInsertAtEventArgs<TItem>>,
|
||||
INotificationHandler<CreateEventArgs<TItem>>,
|
||||
INotificationHandler<InsertEventArgs<TItem>>,
|
||||
INotificationHandler<MoveEventArgs<TItem>>,
|
||||
INotificationHandler<ReplaceEventArgs<TItem>>
|
||||
where TItem :
|
||||
notnull
|
||||
IDisposable
|
||||
{
|
||||
private readonly System.Collections.ObjectModel.ObservableCollection<TItem> collection = [];
|
||||
|
||||
@@ -111,12 +113,6 @@ public partial class ObservableCollection<TItem> :
|
||||
set => SetItem(index, value);
|
||||
}
|
||||
|
||||
public void ResetAndAddRange(Action<ObservableCollection<TItem>> args)
|
||||
{
|
||||
Clear();
|
||||
args.Invoke(this);
|
||||
}
|
||||
|
||||
object? IList.this[int index]
|
||||
{
|
||||
get => collection[index];
|
||||
@@ -136,18 +132,13 @@ public partial class ObservableCollection<TItem> :
|
||||
}
|
||||
}
|
||||
|
||||
public TItem Add() =>
|
||||
public TItem Add() =>
|
||||
Add<TItem>(null, false);
|
||||
|
||||
public TItem Add<T>(params object?[] parameters)
|
||||
where T : TItem => Add<T>(null, false, parameters);
|
||||
where T : TItem => Add<T>(false, parameters);
|
||||
|
||||
public TItem Add<T>(IDisposable? owner,
|
||||
params object?[] parameters)
|
||||
where T : TItem => Add<T>(owner, false, parameters);
|
||||
|
||||
public TItem Add<T>(IDisposable? owner = null,
|
||||
bool scope = false,
|
||||
public TItem Add<T>(bool scope = false,
|
||||
params object?[] parameters)
|
||||
where T :
|
||||
TItem
|
||||
@@ -162,17 +153,6 @@ public partial class ObservableCollection<TItem> :
|
||||
T? item = factory is not null ? factory.Create<T>(parameters) : Factory.Create<T>(parameters);
|
||||
Add(item);
|
||||
|
||||
if (owner is not null)
|
||||
{
|
||||
Disposer.Add(owner, Disposable.Create(() =>
|
||||
{
|
||||
if (item is IRemovable)
|
||||
{
|
||||
Remove(item);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -213,6 +193,20 @@ public partial class ObservableCollection<TItem> :
|
||||
}
|
||||
}
|
||||
|
||||
public void BeginAggregation()
|
||||
{
|
||||
if (this.GetAttribute<AggerateAttribute>() is AggerateAttribute attribute)
|
||||
{
|
||||
if (attribute.Mode == AggerateMode.Reset)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
object? key = this.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key;
|
||||
Publisher.PublishUI(OnPrepareAggregation(key));
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
clearing = true;
|
||||
@@ -220,6 +214,7 @@ public partial class ObservableCollection<TItem> :
|
||||
foreach (TItem item in this.ToList())
|
||||
{
|
||||
Disposer.Dispose(item);
|
||||
Disposer.Remove(this, item);
|
||||
}
|
||||
|
||||
ClearItems();
|
||||
@@ -250,20 +245,6 @@ public partial class ObservableCollection<TItem> :
|
||||
Disposer.Dispose(this);
|
||||
}
|
||||
|
||||
public void BeginAggregation()
|
||||
{
|
||||
if (this.GetAttribute<AggerateAttribute>() is AggerateAttribute attribute)
|
||||
{
|
||||
if (attribute.Mode == AggerateMode.Reset)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
object? key = this.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key;
|
||||
Publisher.PublishUI(OnPrepareAggregation(key));
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<TItem> GetEnumerator() =>
|
||||
collection.GetEnumerator();
|
||||
|
||||
@@ -323,6 +304,27 @@ public partial class ObservableCollection<TItem> :
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(RemoveAtEventArgs<TItem> args)
|
||||
{
|
||||
if (args.Index >= 0 && args.Index <= Count - 1)
|
||||
{
|
||||
RemoveAt(args.Index);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task Handle(RemoveAndInsertAtEventArgs<TItem> args)
|
||||
{
|
||||
if (args.OldIndex >= 0 && args.OldIndex <= Count - 1 && args.Value is TItem item)
|
||||
{
|
||||
RemoveAt(args.OldIndex);
|
||||
Insert(args.NewIndex, item);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public int IndexOf(TItem item) =>
|
||||
collection.IndexOf(item);
|
||||
|
||||
@@ -385,8 +387,10 @@ public partial class ObservableCollection<TItem> :
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Disposer.Dispose(item);
|
||||
Disposer.Remove(this, item);
|
||||
|
||||
RemoveItem(index);
|
||||
|
||||
return true;
|
||||
@@ -419,6 +423,12 @@ public partial class ObservableCollection<TItem> :
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ResetAndAddRange(Action<ObservableCollection<TItem>> args)
|
||||
{
|
||||
Clear();
|
||||
args.Invoke(this);
|
||||
}
|
||||
|
||||
protected virtual void ClearItems() =>
|
||||
collection.Clear();
|
||||
|
||||
@@ -439,7 +449,7 @@ public partial class ObservableCollection<TItem> :
|
||||
}
|
||||
}));
|
||||
|
||||
collection.Insert(index, item);
|
||||
collection.Insert(index > Count ? Count : index, item);
|
||||
}
|
||||
|
||||
protected virtual IAggerate OnPrepareAggregation(object? key) =>
|
||||
@@ -476,7 +486,7 @@ public partial class ObservableCollection<TValue, TViewModel>(IServiceProvider p
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscription subscriber, IDisposer disposer) : ObservableCollection<TViewModel>(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
where TViewModel : notnull
|
||||
where TViewModel : IDisposable
|
||||
{
|
||||
[ObservableProperty]
|
||||
private TValue? value;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record RemoveAndInsertAt
|
||||
{
|
||||
public static RemoveAndInsertAtEventArgs<TValue> As<TValue>(int oldIndex, int newIndex, TValue value) =>
|
||||
new(oldIndex, newIndex, value);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record RemoveAndInsertAtEventArgs<TValue>(int OldIndex, int NewIndex, TValue Value);
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record RemoveAt
|
||||
{
|
||||
public static RemoveAtEventArgs<TValue> As<TValue>(int index) =>
|
||||
new(index);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record RemoveAtEventArgs<TValue>(int Index);
|
||||
@@ -1,3 +1,5 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public record RemoveEventArgs<TValue>(TValue Value);
|
||||
|
||||
public record RemoveAndInsertEventArgs<TValue>(TValue Value);
|
||||
@@ -21,7 +21,7 @@ public class Subscription(SubscriptionCollection subscriptions,
|
||||
return collection;
|
||||
});
|
||||
|
||||
disposer.Add(subscriber, Disposable.Create(() => RemoveSubscriber(subscriber, argumentType)));
|
||||
disposer.Add(subscriber, Disposable.Create(() => RemoveSubscriber(subscriber, subscriptionKey)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,10 +51,9 @@ public class Subscription(SubscriptionCollection subscriptions,
|
||||
|
||||
|
||||
private void RemoveSubscriber(object subscriber,
|
||||
Type argumentType)
|
||||
string key)
|
||||
{
|
||||
string subscriptionKey = $"{argumentType}";
|
||||
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers))
|
||||
if (subscriptions.TryGetValue(key, out List<WeakReference>? subscribers))
|
||||
{
|
||||
for (int i = subscribers.Count - 1; i >= 0; i--)
|
||||
{
|
||||
@@ -66,7 +65,7 @@ public class Subscription(SubscriptionCollection subscriptions,
|
||||
|
||||
if (subscribers.Count == 0)
|
||||
{
|
||||
subscriptions.TryRemove(subscriptionKey, out _);
|
||||
subscriptions.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.Xaml.Interactivity;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
Reference in New Issue
Block a user