Drop ValueViewModel, and expand ObservableCollection to support Value/ViewModel, and Key/Value/ViewModel

This commit is contained in:
TheXamlGuy
2024-10-02 21:47:59 +01:00
parent 08bfa44c4f
commit 855edf7d6d
7 changed files with 250 additions and 129 deletions
+2 -1
View File
@@ -8,7 +8,8 @@ public partial class CommandValueViewModel<TValue>(IServiceProvider provider,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscriber subscriber,
IDisposer disposer) : IDisposer disposer) :
ValueViewModel<TValue>(provider, factory, mediator, publisher, subscriber, disposer) Observable<TValue>(provider, factory, mediator, publisher, subscriber, disposer)
where TValue : notnull
{ {
public IRelayCommand InvokeCommand => public IRelayCommand InvokeCommand =>
new AsyncRelayCommand(InvokeAsync); new AsyncRelayCommand(InvokeAsync);
@@ -1,4 +1,5 @@
namespace Toolkit.Foundation;
namespace Toolkit.Foundation;
public partial class ConfigurationValueViewModel<TConfiguration, TValue>(IServiceProvider provider, public partial class ConfigurationValueViewModel<TConfiguration, TValue>(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
@@ -10,13 +11,83 @@ public partial class ConfigurationValueViewModel<TConfiguration, TValue>(IServic
IWritableConfiguration<TConfiguration> writer, IWritableConfiguration<TConfiguration> writer,
Func<TConfiguration, TValue?> read, Func<TConfiguration, TValue?> read,
Action<TValue?, TConfiguration> write) : Action<TValue?, TConfiguration> write) :
ValueViewModel<TValue>(provider, factory, mediator, publisher, subscriber, disposer), Observable<TValue>(provider, factory, mediator, publisher, subscriber, disposer),
INotificationHandler<ChangedEventArgs<TConfiguration>> INotificationHandler<ChangedEventArgs<TConfiguration>>
where TConfiguration : class where TConfiguration : class
{ {
public Task Handle(ChangedEventArgs<TConfiguration> args) public Task Handle(ChangedEventArgs<TConfiguration> args)
{ {
throw new NotImplementedException();
}
protected override void OnChanged(TValue? value)
{
writer.Write(args => write(value, args));
base.OnChanged(value);
}
public override Task OnActivated()
{
Value = read(configuration);
return base.OnActivated();
}
}
public partial class ConfigurationValueViewModel<TConfiguration, TValue, TItem> :
ObservableCollection<TValue, TItem>,
INotificationHandler<ChangedEventArgs<TConfiguration>>
where TConfiguration : class
where TItem : notnull,
IDisposable
{
private readonly TConfiguration configuration;
private readonly IWritableConfiguration<TConfiguration> writer;
private readonly Func<TConfiguration, TValue?> read;
private readonly Action<TValue?, TConfiguration> write;
public ConfigurationValueViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer,
TConfiguration configuration,
IWritableConfiguration<TConfiguration> writer,
Func<TConfiguration, TValue?> read,
Action<TValue?, TConfiguration> write,
TValue? value = default) : base(provider, factory, mediator, publisher, subscriber, disposer, value)
{
this.configuration = configuration;
this.writer = writer;
this.read = read;
this.write = write;
Value = value;
}
public ConfigurationValueViewModel(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer,
IEnumerable<TItem> items,
TConfiguration configuration,
IWritableConfiguration<TConfiguration> writer,
Func<TConfiguration, TValue?> read,
Action<TValue?, TConfiguration> write,
TValue? value = default) : base(provider, factory, mediator, publisher, subscriber, disposer, items, value)
{
this.configuration = configuration;
this.writer = writer;
this.read = read;
this.write = write;
Value = value;
}
public Task Handle(ChangedEventArgs<TConfiguration> args)
{
throw new NotImplementedException(); throw new NotImplementedException();
} }
+2 -4
View File
@@ -110,7 +110,6 @@ public partial class Observable(IServiceProvider provider,
public partial class Observable<TValue> : public partial class Observable<TValue> :
Observable Observable
where TValue : notnull
{ {
[ObservableProperty] [ObservableProperty]
private TValue? value; private TValue? value;
@@ -126,16 +125,15 @@ public partial class Observable<TValue> :
Value = value; Value = value;
} }
protected virtual void OnValueChanged() protected virtual void OnChanged(TValue? value)
{ {
} }
partial void OnValueChanged(TValue? value) => OnValueChanged(); partial void OnValueChanged(TValue? value) => OnChanged(value);
} }
public partial class Observable<TKey, TValue> : public partial class Observable<TKey, TValue> :
Observable Observable
where TKey : notnull
{ {
[ObservableProperty] [ObservableProperty]
private TKey key; private TKey key;
+110 -98
View File
@@ -7,35 +7,35 @@ using System.Reactive.Disposables;
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public partial class ObservableCollection<TItem> : public partial class ObservableCollection<TViewModel> :
ObservableObject, ObservableObject,
IObservableCollectionViewModel<TItem>, IObservableCollectionViewModel<TViewModel>,
IInitialization, IInitialization,
IActivated, IActivated,
IDeactivating, IDeactivating,
IDeactivated, IDeactivated,
IList<TItem>, IList<TViewModel>,
IList, IList,
IReadOnlyList<TItem>, IReadOnlyList<TViewModel>,
INotifyCollectionChanged, INotifyCollectionChanged,
ICollectionSynchronization<TItem>, ICollectionSynchronization<TViewModel>,
IServiceProviderRequired, IServiceProviderRequired,
IServiceFactoryRequired, IServiceFactoryRequired,
IMediatorRequired, IMediatorRequired,
IPublisherRequired, IPublisherRequired,
IDisposerRequired, IDisposerRequired,
INotificationHandler<RemoveEventArgs<TItem>>, INotificationHandler<RemoveEventArgs<TViewModel>>,
INotificationHandler<RemoveAtEventArgs<TItem>>, INotificationHandler<RemoveAtEventArgs<TViewModel>>,
INotificationHandler<CreateEventArgs<TItem>>, INotificationHandler<CreateEventArgs<TViewModel>>,
INotificationHandler<InsertEventArgs<TItem>>, INotificationHandler<InsertEventArgs<TViewModel>>,
INotificationHandler<MoveEventArgs<TItem>>, INotificationHandler<MoveEventArgs<TViewModel>>,
INotificationHandler<MoveToEventArgs<TItem>>, INotificationHandler<MoveToEventArgs<TViewModel>>,
INotificationHandler<ReplaceEventArgs<TItem>>, INotificationHandler<ReplaceEventArgs<TViewModel>>,
INotificationHandler<SelectionEventArgs<TItem>> INotificationHandler<SelectionEventArgs<TViewModel>>
where TItem : notnull, where TViewModel : notnull,
IDisposable IDisposable
{ {
private readonly System.Collections.ObjectModel.ObservableCollection<TItem> collection = []; private readonly System.Collections.ObjectModel.ObservableCollection<TViewModel> collection = [];
private readonly IDispatcher dispatcher; private readonly IDispatcher dispatcher;
@@ -55,7 +55,7 @@ public partial class ObservableCollection<TItem> :
private bool isInitialized; private bool isInitialized;
[ObservableProperty] [ObservableProperty]
private TItem? selectedItem; private TViewModel? selectedItem;
public ObservableCollection(IServiceProvider provider, public ObservableCollection(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
@@ -81,7 +81,7 @@ public partial class ObservableCollection<TItem> :
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscriber subscriber,
IDisposer disposer, IDisposer disposer,
IEnumerable<TItem> items) IEnumerable<TViewModel> items)
{ {
Provider = provider; Provider = provider;
Factory = factory; Factory = factory;
@@ -104,7 +104,7 @@ public partial class ObservableCollection<TItem> :
bool IList.IsFixedSize => false; bool IList.IsFixedSize => false;
bool ICollection<TItem>.IsReadOnly => false; bool ICollection<TViewModel>.IsReadOnly => false;
bool IList.IsReadOnly => false; bool IList.IsReadOnly => false;
@@ -120,7 +120,7 @@ public partial class ObservableCollection<TItem> :
object ICollection.SyncRoot => this; object ICollection.SyncRoot => this;
public TItem this[int index] public TViewModel this[int index]
{ {
get => collection[index]; get => collection[index];
set => SetItem(index, value); set => SetItem(index, value);
@@ -131,11 +131,11 @@ public partial class ObservableCollection<TItem> :
get => index >= 0 && collection.Count > 0 ? collection[index] : null; get => index >= 0 && collection.Count > 0 ? collection[index] : null;
set set
{ {
TItem? item = default; TViewModel? item = default;
try try
{ {
item = (TItem)value!; item = (TViewModel)value!;
} }
catch (InvalidCastException) catch (InvalidCastException)
{ {
@@ -145,12 +145,12 @@ public partial class ObservableCollection<TItem> :
} }
} }
private Func<TItem>? defaultSelectionFactory; private Func<TViewModel>? defaultSelectionFactory;
public void SetSource(IList<TItem> source, public void SetSource(IList<TViewModel> source,
Func<TItem>? defaultSelectionFactory) Func<TViewModel>? defaultSelectionFactory)
{ {
foreach (TItem item in source) foreach (TViewModel item in source)
{ {
Add(item); Add(item);
} }
@@ -176,7 +176,7 @@ public partial class ObservableCollection<TItem> :
case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Add:
if (args.NewItems is not null) if (args.NewItems is not null)
{ {
foreach (TItem newItem in args.NewItems) foreach (TViewModel newItem in args.NewItems)
{ {
Add(newItem); Add(newItem);
} }
@@ -186,9 +186,9 @@ public partial class ObservableCollection<TItem> :
case NotifyCollectionChangedAction.Remove: case NotifyCollectionChangedAction.Remove:
if (args.OldItems is not null) if (args.OldItems is not null)
{ {
foreach (TItem oldItem in args.OldItems) foreach (TViewModel oldItem in args.OldItems)
{ {
if (this.FirstOrDefault(x => x.Equals(oldItem)) is TItem removedItem) if (this.FirstOrDefault(x => x.Equals(oldItem)) is TViewModel removedItem)
{ {
Remove(removedItem); Remove(removedItem);
} }
@@ -199,9 +199,9 @@ public partial class ObservableCollection<TItem> :
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
Clear(); Clear();
if (sender is IEnumerable<TItem> collection) if (sender is IEnumerable<TViewModel> collection)
{ {
foreach (TItem item in collection) foreach (TViewModel item in collection)
{ {
Add(item); Add(item);
} }
@@ -227,8 +227,8 @@ public partial class ObservableCollection<TItem> :
return Task.CompletedTask; return Task.CompletedTask;
} }
public TItem Add<T>(params object?[] parameters) public TViewModel Add<T>(params object?[] parameters)
where T : TItem where T : TViewModel
{ {
T? item = Factory.Create<T>(args => T? item = Factory.Create<T>(args =>
{ {
@@ -242,7 +242,7 @@ public partial class ObservableCollection<TItem> :
return item; return item;
} }
public void Add(TItem item) public void Add(TViewModel item)
{ {
int index = collection.Count; int index = collection.Count;
InsertItem(index, item); InsertItem(index, item);
@@ -253,16 +253,16 @@ public partial class ObservableCollection<TItem> :
public void Add(object item) public void Add(object item)
{ {
int index = collection.Count; int index = collection.Count;
InsertItem(index, (TItem)item); InsertItem(index, (TViewModel)item);
} }
int IList.Add(object? value) int IList.Add(object? value)
{ {
TItem? item = default; TViewModel? item = default;
try try
{ {
item = (TItem)value!; item = (TViewModel)value!;
} }
catch (InvalidCastException) catch (InvalidCastException)
{ {
@@ -272,9 +272,9 @@ public partial class ObservableCollection<TItem> :
return Count - 1; return Count - 1;
} }
public void AddRange(IEnumerable<TItem> items) public void AddRange(IEnumerable<TViewModel> items)
{ {
foreach (TItem? item in items) foreach (TViewModel? item in items)
{ {
if (item is IInitialization initialization) if (item is IInitialization initialization)
{ {
@@ -285,7 +285,7 @@ public partial class ObservableCollection<TItem> :
} }
} }
public void Reset(Action<ObservableCollection<TItem>> factory, bool disposeItems = true) public void Reset(Action<ObservableCollection<TViewModel>> factory, bool disposeItems = true)
{ {
SelectedItem = default; SelectedItem = default;
@@ -298,7 +298,7 @@ public partial class ObservableCollection<TItem> :
isClearing = true; isClearing = true;
if (disposeItems) if (disposeItems)
{ {
foreach (TItem item in this.ToList()) foreach (TViewModel item in this.ToList())
{ {
Disposer.Dispose(item); Disposer.Dispose(item);
Disposer.Remove(this, item); Disposer.Remove(this, item);
@@ -312,7 +312,7 @@ public partial class ObservableCollection<TItem> :
public void Clear() public void Clear()
{ {
isClearing = true; isClearing = true;
foreach (TItem item in this.ToList()) foreach (TViewModel item in this.ToList())
{ {
Disposer.Dispose(item); Disposer.Dispose(item);
Disposer.Remove(this, item); Disposer.Remove(this, item);
@@ -330,17 +330,17 @@ public partial class ObservableCollection<TItem> :
} }
} }
public bool Contains(TItem item) => public bool Contains(TViewModel item) =>
collection.Contains(item); collection.Contains(item);
bool IList.Contains(object? value) => bool IList.Contains(object? value) =>
IsCompatibleObject(value) && Contains((TItem)value!); IsCompatibleObject(value) && Contains((TViewModel)value!);
public void CopyTo(TItem[] array, int index) => public void CopyTo(TViewModel[] array, int index) =>
collection.CopyTo(array, index); collection.CopyTo(array, index);
void ICollection.CopyTo(Array array, int index) => void ICollection.CopyTo(Array array, int index) =>
collection.CopyTo((TItem[])array, index); collection.CopyTo((TViewModel[])array, index);
public virtual Task OnDeactivated() public virtual Task OnDeactivated()
{ {
@@ -369,17 +369,17 @@ public partial class ObservableCollection<TItem> :
Publisher.Publish(builder.Value, builder.Key); Publisher.Publish(builder.Value, builder.Key);
} }
public IEnumerator<TItem> GetEnumerator() => public IEnumerator<TViewModel> GetEnumerator() =>
collection.GetEnumerator(); collection.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => IEnumerator IEnumerable.GetEnumerator() =>
((IEnumerable)collection).GetEnumerator(); ((IEnumerable)collection).GetEnumerator();
public Task Handle(RemoveEventArgs<TItem> args) public Task Handle(RemoveEventArgs<TViewModel> args)
{ {
if (IsActivated) if (IsActivated)
{ {
foreach (TItem item in this.ToList()) foreach (TViewModel item in this.ToList())
{ {
if (args.Sender is not null && args.Sender.Equals(item)) if (args.Sender is not null && args.Sender.Equals(item))
{ {
@@ -395,11 +395,11 @@ public partial class ObservableCollection<TItem> :
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task Handle(CreateEventArgs<TItem> args) public Task Handle(CreateEventArgs<TViewModel> args)
{ {
if (IsActivated) if (IsActivated)
{ {
if (args.Sender is TItem item) if (args.Sender is TViewModel item)
{ {
Add(item); Add(item);
} }
@@ -412,11 +412,11 @@ public partial class ObservableCollection<TItem> :
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task Handle(InsertEventArgs<TItem> args) public Task Handle(InsertEventArgs<TViewModel> args)
{ {
if (IsActivated) if (IsActivated)
{ {
if (args.Sender is TItem item) if (args.Sender is TViewModel item)
{ {
Insert(args.Index, item); Insert(args.Index, item);
} }
@@ -429,7 +429,7 @@ public partial class ObservableCollection<TItem> :
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task Handle(MoveToEventArgs<TItem> args) public Task Handle(MoveToEventArgs<TViewModel> args)
{ {
if (IsActivated) if (IsActivated)
{ {
@@ -443,11 +443,11 @@ public partial class ObservableCollection<TItem> :
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task Handle(MoveEventArgs<TItem> args) public Task Handle(MoveEventArgs<TViewModel> args)
{ {
if (IsActivated) if (IsActivated)
{ {
if (args.Sender is TItem item) if (args.Sender is TViewModel item)
{ {
Move(args.Index, item); Move(args.Index, item);
} }
@@ -460,11 +460,11 @@ public partial class ObservableCollection<TItem> :
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task Handle(ReplaceEventArgs<TItem> args) public Task Handle(ReplaceEventArgs<TViewModel> args)
{ {
if (IsActivated) if (IsActivated)
{ {
if (args.Sender is TItem item) if (args.Sender is TViewModel item)
{ {
Replace(args.Index, item); Replace(args.Index, item);
} }
@@ -477,7 +477,7 @@ public partial class ObservableCollection<TItem> :
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task Handle(RemoveAtEventArgs<TItem> args) public Task Handle(RemoveAtEventArgs<TViewModel> args)
{ {
if (IsActivated) if (IsActivated)
{ {
@@ -495,15 +495,15 @@ public partial class ObservableCollection<TItem> :
return Task.CompletedTask; return Task.CompletedTask;
} }
public Task Handle(SelectionEventArgs<TItem> args) => public Task Handle(SelectionEventArgs<TViewModel> args) =>
Task.CompletedTask; Task.CompletedTask;
public int IndexOf(TItem item) => public int IndexOf(TViewModel item) =>
collection.IndexOf(item); collection.IndexOf(item);
int IList.IndexOf(object? value) => int IList.IndexOf(object? value) =>
IsCompatibleObject(value) ? IsCompatibleObject(value) ?
IndexOf((TItem)value!) : -1; IndexOf((TViewModel)value!) : -1;
public virtual void OnInitialize() public virtual void OnInitialize()
{ {
@@ -524,10 +524,10 @@ public partial class ObservableCollection<TItem> :
Activate(); Activate();
} }
public TItem Insert<T>(int index = 0, public TViewModel Insert<T>(int index = 0,
params object?[] parameters) params object?[] parameters)
where T : where T :
TItem TViewModel
{ {
T? item = Factory.Create<T>(args => T? item = Factory.Create<T>(args =>
{ {
@@ -544,7 +544,7 @@ public partial class ObservableCollection<TItem> :
} }
public void Insert(int index, public void Insert(int index,
TItem item) TViewModel item)
{ {
InsertItem(index, item); InsertItem(index, item);
UpdateSelection(item); UpdateSelection(item);
@@ -553,7 +553,7 @@ public partial class ObservableCollection<TItem> :
void IList.Insert(int index, void IList.Insert(int index,
object? value) object? value)
{ {
if (value is TItem item) if (value is TViewModel item)
{ {
Insert(index, item); Insert(index, item);
UpdateSelection(item); UpdateSelection(item);
@@ -567,7 +567,7 @@ public partial class ObservableCollection<TItem> :
return false; return false;
} }
TItem item = this[oldIndex]; TViewModel item = this[oldIndex];
bool moveSelection = false; bool moveSelection = false;
if (item is ISelectable oldSelection) if (item is ISelectable oldSelection)
@@ -594,7 +594,7 @@ public partial class ObservableCollection<TItem> :
return true; return true;
} }
public bool Move(int index, TItem item) public bool Move(int index, TViewModel item)
{ {
int oldIndex = collection.IndexOf(item); int oldIndex = collection.IndexOf(item);
if (oldIndex < 0) if (oldIndex < 0)
@@ -608,7 +608,7 @@ public partial class ObservableCollection<TItem> :
return true; return true;
} }
public bool Remove(TItem item) public bool Remove(TViewModel item)
{ {
int index = collection.IndexOf(item); int index = collection.IndexOf(item);
if (index < 0) if (index < 0)
@@ -619,13 +619,13 @@ public partial class ObservableCollection<TItem> :
Disposer.Dispose(item); Disposer.Dispose(item);
Disposer.Remove(this, item); Disposer.Remove(this, item);
TItem? oldSelection = SelectedItem; TViewModel? oldSelection = SelectedItem;
RemoveItem(index); RemoveItem(index);
if (item.Equals(oldSelection)) if (item.Equals(oldSelection))
{ {
int newIndex = Math.Min(index, Count - 1); int newIndex = Math.Min(index, Count - 1);
TItem? selectedItem = newIndex >= 0 ? this[newIndex] : default; TViewModel? selectedItem = newIndex >= 0 ? this[newIndex] : default;
dispatcher.Invoke(() => SelectedItem = selectedItem); dispatcher.Invoke(() => SelectedItem = selectedItem);
} }
@@ -636,7 +636,7 @@ public partial class ObservableCollection<TItem> :
{ {
if (IsCompatibleObject(value)) if (IsCompatibleObject(value))
{ {
Remove((TItem)value!); Remove((TViewModel)value!);
} }
} }
@@ -644,7 +644,7 @@ public partial class ObservableCollection<TItem> :
RemoveItem(index); RemoveItem(index);
public bool Replace(int index, public bool Replace(int index,
TItem item) TViewModel item)
{ {
if (index <= Count - 1) if (index <= Count - 1)
{ {
@@ -688,13 +688,13 @@ public partial class ObservableCollection<TItem> :
} }
protected virtual ActivationBuilder ActivationBuilder() => protected virtual ActivationBuilder ActivationBuilder() =>
new(new ActivationEventArgs<TItem>()); new(new ActivationEventArgs<TViewModel>());
protected virtual void ClearItems() => protected virtual void ClearItems() =>
collection.Clear(); collection.Clear();
protected virtual void InsertItem(int index, protected virtual void InsertItem(int index,
TItem item) TViewModel item)
{ {
Disposer.Add(this, item); Disposer.Add(this, item);
Disposer.Add(item, Disposable.Create(() => Disposer.Add(item, Disposable.Create(() =>
@@ -716,11 +716,11 @@ public partial class ObservableCollection<TItem> :
protected virtual void RemoveItem(int index) => protected virtual void RemoveItem(int index) =>
collection.RemoveAt(index); collection.RemoveAt(index);
protected virtual void SetItem(int index, TItem item) => protected virtual void SetItem(int index, TViewModel item) =>
collection[index] = item; collection[index] = item;
private static bool IsCompatibleObject(object? value) => private static bool IsCompatibleObject(object? value) =>
(value is TItem) || (value == null && default(TItem) == null); (value is TViewModel) || (value == null && default(TViewModel) == null);
private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs args) private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs args)
{ {
@@ -740,7 +740,7 @@ public partial class ObservableCollection<TItem> :
} }
} }
partial void OnSelectedItemChanged(TItem? oldValue, TItem? newValue) partial void OnSelectedItemChanged(TViewModel? oldValue, TViewModel? newValue)
{ {
if (oldValue is ISelectable oldSelection) if (oldValue is ISelectable oldSelection)
{ {
@@ -760,7 +760,7 @@ public partial class ObservableCollection<TItem> :
{ {
} }
private void UpdateSelection(TItem item) private void UpdateSelection(TViewModel item)
{ {
if (item is ISelectable newSelection) if (item is ISelectable newSelection)
{ {
@@ -777,35 +777,53 @@ public partial class ObservableCollection<TItem> :
} }
} }
public partial class ObservableCollection<TValue, TViewModel>(IServiceProvider provider, public partial class ObservableCollection<TValue, TViewModel> :
ObservableCollection<TViewModel>
where TViewModel : IDisposable
{
[ObservableProperty]
private TValue? value;
public ObservableCollection(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscriber subscriber,
IDisposer disposer, IDisposer disposer,
TValue value) : ObservableCollection<TViewModel>(provider, factory, mediator, publisher, subscriber, disposer) TValue? value = default) : base(provider, factory, mediator, publisher, subscriber, disposer)
where TViewModel : notnull, IDisposable
{
[ObservableProperty]
private TValue value = value;
protected virtual void OnValueChanged()
{ {
Value = value;
} }
partial void OnValueChanged(TValue value) => OnValueChanged(); public ObservableCollection(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer,
IEnumerable<TViewModel> items,
TValue? value = default) : base(provider, factory, mediator, publisher, subscriber, disposer, items)
{
Value = value;
}
protected virtual void OnChanged(TValue? value)
{
}
partial void OnValueChanged(TValue? value) => OnChanged(value);
} }
public partial class ObservableCollection<TViewModel, TKey, TValue> : public partial class ObservableCollection<TViewModel, TKey, TValue> :
ObservableCollection<TViewModel> ObservableCollection<TViewModel>
where TViewModel : notnull, IDisposable where TViewModel : IDisposable
where TKey : notnull
{ {
[ObservableProperty] [ObservableProperty]
private TKey key; private TKey key;
[ObservableProperty] [ObservableProperty]
private TValue value; private TValue? value;
public ObservableCollection(IServiceProvider provider, public ObservableCollection(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
@@ -814,7 +832,7 @@ public partial class ObservableCollection<TViewModel, TKey, TValue> :
ISubscriber subscriber, ISubscriber subscriber,
IDisposer disposer, IDisposer disposer,
TKey key, TKey key,
TValue value) : base(provider, factory, mediator, publisher, subscriber, disposer) TValue? value = default) : base(provider, factory, mediator, publisher, subscriber, disposer)
{ {
Key = key; Key = key;
Value = value; Value = value;
@@ -828,17 +846,11 @@ public partial class ObservableCollection<TViewModel, TKey, TValue> :
IDisposer disposer, IDisposer disposer,
IEnumerable<TViewModel> items, IEnumerable<TViewModel> items,
TKey key, TKey key,
TValue value) : base(provider, factory, mediator, publisher, subscriber, disposer, items) TValue? value = default) : base(provider, factory, mediator, publisher, subscriber, disposer, items)
{ {
Key = key; Key = key;
Value = value; Value = value;
} }
protected virtual void OnValueChanged()
{
}
partial void OnValueChanged(TValue value) => OnValueChanged();
} }
public class ObservableCollection : public class ObservableCollection :
-21
View File
@@ -1,21 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace Toolkit.Foundation;
public partial class ValueViewModel<TValue>(IServiceProvider provider,
IServiceFactory factory,
IMediator mediator,
IPublisher publisher,
ISubscriber subscriber,
IDisposer disposer) :
Observable(provider, factory, mediator, publisher, subscriber, disposer)
{
[ObservableProperty]
private TValue? value;
protected virtual void OnChanged(TValue? value)
{
}
partial void OnValueChanged(TValue? value) => OnChanged(value);
}
@@ -14,7 +14,7 @@ public class EventListenerBehaviour :
public static readonly StyledProperty<object> SourceProperty = public static readonly StyledProperty<object> SourceProperty =
AvaloniaProperty.Register<EventListenerBehaviour, object>(nameof(Source)); AvaloniaProperty.Register<EventListenerBehaviour, object>(nameof(Source));
private Delegate? eventHandler; private readonly Delegate? eventHandler;
private object? resolvedSource; private object? resolvedSource;
static EventListenerBehaviour() static EventListenerBehaviour()
@@ -2,6 +2,66 @@
<Styles.Resources> <Styles.Resources>
<ResourceDictionary> <ResourceDictionary>
<FontFamily x:Key="FluentThemeFontFamily">/Fonts/#FluentSystemIcons-Resizable</FontFamily> <FontFamily x:Key="FluentThemeFontFamily">/Fonts/#FluentSystemIcons-Resizable</FontFamily>
<ControlTheme x:Key="TextBoxButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{DynamicResource TextControlButtonForeground}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="{DynamicResource TextControlButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
<Setter Property="Width" Value="30" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Padding" Value="{StaticResource HelperButtonThemePadding}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Focusable" Value="False" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<ControlTemplate>
<Border
Name="ButtonLayoutGrid"
Margin="{DynamicResource TextBoxInnerButtonMargin}"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<ContentPresenter
Name="PART_ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
RecognizesAccessKey="True" />
</Border>
</ControlTemplate>
</Setter>
<Style Selector="^:pointerover">
<Style Selector="^ /template/ Border#ButtonLayoutGrid">
<Setter Property="Background" Value="{DynamicResource TextControlButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource TextControlButtonBorderBrushPointerOver}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource TextControlButtonForegroundPointerOver}" />
</Style>
</Style>
<Style Selector="^:pressed">
<Style Selector="^ /template/ Border#ButtonLayoutGrid">
<Setter Property="Background" Value="{DynamicResource TextControlButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource TextControlButtonBorderBrushPressed}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource TextControlButtonForegroundPressed}" />
</Style>
</Style>
<Style Selector="^:disabled /template/ Border#ButtonLayoutGrid">
<Setter Property="Opacity" Value="0" />
</Style>
</ControlTheme>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<MergeResourceInclude Source="../CarouselView/CarouselView.axaml" /> <MergeResourceInclude Source="../CarouselView/CarouselView.axaml" />
<MergeResourceInclude Source="../PersonPicture/PersonPicture.axaml" /> <MergeResourceInclude Source="../PersonPicture/PersonPicture.axaml" />