rewrite ObservableCollectionViewModel

This commit is contained in:
TheXamlGuy
2024-01-10 20:06:52 +00:00
parent d7d90b3d54
commit d6df6c5eb9
4 changed files with 180 additions and 17 deletions
+4 -1
View File
@@ -52,13 +52,16 @@ public partial class App :
{ {
static IEnumerable<WidgetContainerViewModel> Resolve(IServiceProvider services) static IEnumerable<WidgetContainerViewModel> Resolve(IServiceProvider services)
{ {
int index = 0;
foreach (IWidgetContext widgetContext in services.GetServices<IWidgetContext>()) foreach (IWidgetContext widgetContext in services.GetServices<IWidgetContext>())
{ {
if (widgetContext.ServiceProvider.GetServices<IWidgetViewModel>() is if (widgetContext.ServiceProvider.GetServices<IWidgetViewModel>() is
IEnumerable<IWidgetViewModel> viewModels) IEnumerable<IWidgetViewModel> viewModels)
{ {
yield return (WidgetContainerViewModel)ActivatorUtilities.CreateInstance(widgetContext.ServiceProvider, yield return (WidgetContainerViewModel)ActivatorUtilities.CreateInstance(widgetContext.ServiceProvider,
typeof(WidgetContainerViewModel), viewModels); typeof(WidgetContainerViewModel), viewModels, index % 2 == 0);
index++;
} }
} }
} }
@@ -4,11 +4,24 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="using:Hyperbar.Windows.UI"> xmlns:ui="using:Hyperbar.Windows.UI">
<ItemsControl ItemTemplateSelector="{Binding Converter={ui:DataTemplateConverter}}" ItemsSource="{Binding}"> <Grid>
<ItemsControl.ItemsPanel> <Grid.ColumnDefinitions>
<ItemsPanelTemplate> <ColumnDefinition Width="Auto" />
<StackPanel Orientation="Horizontal" /> <ColumnDefinition Width="*" />
</ItemsPanelTemplate> </Grid.ColumnDefinitions>
</ItemsControl.ItemsPanel> <Rectangle
</ItemsControl> Width="1"
Margin="6,0,6,0"
Fill="Red" />
<ItemsControl
Grid.Column="1"
ItemTemplateSelector="{Binding Converter={ui:DataTemplateConverter}}"
ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</UserControl> </UserControl>
+146 -5
View File
@@ -1,14 +1,21 @@
using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace Hyperbar; namespace Hyperbar;
public partial class ObservableCollectionViewModel<TItem> :
public class ObservableCollectionViewModel<TItem> : ObservableObject,
ObservableCollection<TItem>, IList<TItem>,
IList,
IReadOnlyList<TItem>,
INotifyCollectionChanged,
INotificationHandler<CollectionChanged<IEnumerable<TItem>>> INotificationHandler<CollectionChanged<IEnumerable<TItem>>>
{ {
private readonly IServiceFactory serviceFactory; public ObservableCollection<TItem> collection = [];
private readonly SynchronizationContext? context; private readonly SynchronizationContext? context;
private readonly IServiceFactory serviceFactory;
public ObservableCollectionViewModel(IServiceFactory serviceFactory, public ObservableCollectionViewModel(IServiceFactory serviceFactory,
IMediator mediator) IMediator mediator)
@@ -17,6 +24,8 @@ public class ObservableCollectionViewModel<TItem> :
this.serviceFactory = serviceFactory; this.serviceFactory = serviceFactory;
mediator.Subscribe(this); mediator.Subscribe(this);
collection.CollectionChanged += OnCollectionChanged;
} }
public ObservableCollectionViewModel(IServiceFactory serviceFactory, public ObservableCollectionViewModel(IServiceFactory serviceFactory,
@@ -28,9 +37,56 @@ public class ObservableCollectionViewModel<TItem> :
this.serviceFactory = serviceFactory; this.serviceFactory = serviceFactory;
mediator.Subscribe(this); mediator.Subscribe(this);
collection.CollectionChanged += OnCollectionChanged;
AddRange(items); AddRange(items);
} }
public event NotifyCollectionChangedEventHandler? CollectionChanged;
public int Count => collection.Count;
bool IList.IsFixedSize => false;
bool ICollection<TItem>.IsReadOnly => false;
bool IList.IsReadOnly => false;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
protected IList<TItem> 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() public TItem Add()
{ {
TItem? item = serviceFactory.Create<TItem>(); TItem? item = serviceFactory.Create<TItem>();
@@ -58,6 +114,29 @@ public class ObservableCollectionViewModel<TItem> :
return item; 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<TItem> items) public void AddRange(IEnumerable<TItem> items)
{ {
foreach (TItem? item in items) foreach (TItem? item in items)
@@ -65,6 +144,19 @@ public class ObservableCollectionViewModel<TItem> :
context?.Post(state => Add(item), null); context?.Post(state => Add(item), null);
} }
} }
public void Clear() => ClearItems();
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<TItem> GetEnumerator() => collection.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)collection).GetEnumerator();
public ValueTask Handle(CollectionChanged<IEnumerable<TItem>> notification, public ValueTask Handle(CollectionChanged<IEnumerable<TItem>> notification,
CancellationToken cancellationToken) CancellationToken cancellationToken)
@@ -74,6 +166,55 @@ public class ObservableCollectionViewModel<TItem> :
return ValueTask.CompletedTask; 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) : public class ObservableCollectionViewModel(IServiceFactory serviceFactory, IMediator mediator) :
+8 -2
View File
@@ -1,12 +1,18 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace Hyperbar; namespace Hyperbar;
public class WidgetContainerViewModel(ITemplateFactory templateFactory, public partial class WidgetContainerViewModel(ITemplateFactory templateFactory,
IServiceFactory serviceFactory, IServiceFactory serviceFactory,
IMediator mediator, IMediator mediator,
IEnumerable<IWidgetViewModel> items) : IEnumerable<IWidgetViewModel> items,
bool alternate) :
ObservableCollectionViewModel<IWidgetViewModel>(serviceFactory, mediator, items), ObservableCollectionViewModel<IWidgetViewModel>(serviceFactory, mediator, items),
ITemplatedViewModel ITemplatedViewModel
{ {
[ObservableProperty]
private bool alternate = alternate;
public ITemplateFactory TemplateFactory => templateFactory; public ITemplateFactory TemplateFactory => templateFactory;
} }