From d6df6c5eb96ec7c05790edaef59d907d17fbe563 Mon Sep 17 00:00:00 2001 From: TheXamlGuy Date: Wed, 10 Jan 2024 20:06:52 +0000 Subject: [PATCH] rewrite ObservableCollectionViewModel --- Hyperbar.Windows/App.xaml.cs | 5 +- .../Views/WidgetContainerView.xaml | 27 ++- .../Views/ObservableCollectionViewModel.cs | 155 +++++++++++++++++- Hyperbar/Views/WidgetContainerViewModel.cs | 10 +- 4 files changed, 180 insertions(+), 17 deletions(-) diff --git a/Hyperbar.Windows/App.xaml.cs b/Hyperbar.Windows/App.xaml.cs index f3db736..149d2fe 100644 --- a/Hyperbar.Windows/App.xaml.cs +++ b/Hyperbar.Windows/App.xaml.cs @@ -52,13 +52,16 @@ public partial class App : { static IEnumerable Resolve(IServiceProvider services) { + int index = 0; foreach (IWidgetContext widgetContext in services.GetServices()) { if (widgetContext.ServiceProvider.GetServices() is IEnumerable viewModels) { yield return (WidgetContainerViewModel)ActivatorUtilities.CreateInstance(widgetContext.ServiceProvider, - typeof(WidgetContainerViewModel), viewModels); + typeof(WidgetContainerViewModel), viewModels, index % 2 == 0); + + index++; } } } diff --git a/Hyperbar.Windows/Views/WidgetContainerView.xaml b/Hyperbar.Windows/Views/WidgetContainerView.xaml index 2723fad..0eca26f 100644 --- a/Hyperbar.Windows/Views/WidgetContainerView.xaml +++ b/Hyperbar.Windows/Views/WidgetContainerView.xaml @@ -4,11 +4,24 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ui="using:Hyperbar.Windows.UI"> - - - - - - - + + + + + + + + + + + + + + diff --git a/Hyperbar/Views/ObservableCollectionViewModel.cs b/Hyperbar/Views/ObservableCollectionViewModel.cs index 9b9c599..91bb07a 100644 --- a/Hyperbar/Views/ObservableCollectionViewModel.cs +++ b/Hyperbar/Views/ObservableCollectionViewModel.cs @@ -1,22 +1,31 @@ -using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.ComponentModel; +using System.Collections; +using System.Collections.ObjectModel; +using System.Collections.Specialized; namespace Hyperbar; - -public class ObservableCollectionViewModel : - ObservableCollection, +public partial class ObservableCollectionViewModel : + ObservableObject, + IList, + IList, + IReadOnlyList, + INotifyCollectionChanged, INotificationHandler>> { - private readonly IServiceFactory serviceFactory; + public ObservableCollection collection = []; private readonly SynchronizationContext? context; + private readonly IServiceFactory serviceFactory; - public ObservableCollectionViewModel(IServiceFactory serviceFactory, + public ObservableCollectionViewModel(IServiceFactory serviceFactory, IMediator mediator) { context = SynchronizationContext.Current; this.serviceFactory = serviceFactory; mediator.Subscribe(this); + + collection.CollectionChanged += OnCollectionChanged; } public ObservableCollectionViewModel(IServiceFactory serviceFactory, @@ -28,9 +37,56 @@ public class ObservableCollectionViewModel : this.serviceFactory = serviceFactory; mediator.Subscribe(this); + collection.CollectionChanged += OnCollectionChanged; + AddRange(items); } + public event NotifyCollectionChangedEventHandler? CollectionChanged; + + public int Count => collection.Count; + + bool IList.IsFixedSize => false; + + bool ICollection.IsReadOnly => false; + + bool IList.IsReadOnly => false; + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot => this; + + protected IList Items => collection; + + public TItem this[int index] + { + get => collection[index]; + set + { + SetItem(index, value); + } + } + + object? IList.this[int index] + { + get => collection[index]; + set + { + TItem? item = default; + + try + { + item = (TItem)value!; + } + catch (InvalidCastException) + { + + } + + this[index] = item!; + } + } + public TItem Add() { TItem? item = serviceFactory.Create(); @@ -58,6 +114,29 @@ public class ObservableCollectionViewModel : return item; } + public void Add(TItem item) + { + int index = collection.Count; + InsertItem(index, item); + } + + int IList.Add(object? value) + { + TItem? item = default; + + try + { + item = (TItem)value!; + } + catch (InvalidCastException) + { + + } + + Add(item!); + return Count - 1; + } + public void AddRange(IEnumerable items) { foreach (TItem? item in items) @@ -65,8 +144,21 @@ public class ObservableCollectionViewModel : context?.Post(state => Add(item), null); } } + public void Clear() => ClearItems(); - public ValueTask Handle(CollectionChanged> notification, + public bool Contains(TItem item) => collection.Contains(item); + + bool IList.Contains(object? value) => IsCompatibleObject(value) && Contains((TItem)value!); + + public void CopyTo(TItem[] array, int index) => collection.CopyTo(array, index); + + void ICollection.CopyTo(Array array, int index) => collection.CopyTo((TItem[])array, index); + + public IEnumerator GetEnumerator() => collection.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)collection).GetEnumerator(); + + public ValueTask Handle(CollectionChanged> notification, CancellationToken cancellationToken) { context?.Post(state => Clear(), null); @@ -74,6 +166,55 @@ public class ObservableCollectionViewModel : return ValueTask.CompletedTask; } + + public int IndexOf(TItem item) => collection.IndexOf(item); + + int IList.IndexOf(object? value) => IsCompatibleObject(value) ? IndexOf((TItem)value!) : -1; + + public void Insert(int index, TItem item) => InsertItem(index, item); + + void IList.Insert(int index, object? value) + { + if (value is TItem item) + { + Insert(index, item); + } + } + + public bool Remove(TItem item) + { + int index = collection.IndexOf(item); + if (index < 0) return false; + RemoveItem(index); + return true; + } + + void IList.Remove(object? value) + { + if (IsCompatibleObject(value)) + { + Remove((TItem)value!); + } + } + public void RemoveAt(int index) => RemoveItem(index); + + protected virtual void ClearItems() => collection.Clear(); + + protected virtual void InsertItem(int index, TItem value) + { + if (value is TItem item) + { + collection.Insert(index, item); + } + } + + protected virtual void RemoveItem(int index) => collection.RemoveAt(index); + + protected virtual void SetItem(int index, TItem item) => collection[index] = item; + + private static bool IsCompatibleObject(object? value) => (value is TItem) || (value == null && default(TItem) == null); + + private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs args) => CollectionChanged?.Invoke(this, args); } public class ObservableCollectionViewModel(IServiceFactory serviceFactory, IMediator mediator) : diff --git a/Hyperbar/Views/WidgetContainerViewModel.cs b/Hyperbar/Views/WidgetContainerViewModel.cs index 83196e0..a35f702 100644 --- a/Hyperbar/Views/WidgetContainerViewModel.cs +++ b/Hyperbar/Views/WidgetContainerViewModel.cs @@ -1,12 +1,18 @@  +using CommunityToolkit.Mvvm.ComponentModel; + namespace Hyperbar; -public class WidgetContainerViewModel(ITemplateFactory templateFactory, +public partial class WidgetContainerViewModel(ITemplateFactory templateFactory, IServiceFactory serviceFactory, IMediator mediator, - IEnumerable items) : + IEnumerable items, + bool alternate) : ObservableCollectionViewModel(serviceFactory, mediator, items), ITemplatedViewModel { + [ObservableProperty] + private bool alternate = alternate; + public ITemplateFactory TemplateFactory => templateFactory; } \ No newline at end of file