From a99b10ca49b09c8e44c1db017be3f2d77cb17091 Mon Sep 17 00:00:00 2001 From: neuecc Date: Thu, 8 Aug 2024 18:42:03 +0900 Subject: [PATCH] Add ICollectionEventDispatcher, ToNotifyCollectionChanged(ICollectionEventDispatcher) --- README.md | 27 +++- sandbox/WpfApp/MainWindow.xaml | 1 + sandbox/WpfApp/MainWindow.xaml.cs | 31 ++++- sandbox/WpfApp/WpfApp.csproj | 3 +- .../ICollectionEventDispatcher.cs | 119 ++++++++++++++++++ .../IObservableCollection.cs | 1 + .../Internal/FreezedView.cs | 14 ++- ...NotifyCollectionChangedSynchronizedView.cs | 65 ++++++++-- .../Internal/SortedView.cs | 10 +- .../Internal/SortedViewViewComparer.cs | 10 +- .../ObservableDictionary.Views.cs | 10 +- .../ObservableHashSet.Views.cs | 10 +- .../ObservableList.Views.cs | 36 +++--- .../ObservableQueue.Views.cs | 10 +- .../ObservableRingBuffer.Views.cs | 10 +- .../ObservableStack.Views.cs | 10 +- 16 files changed, 327 insertions(+), 40 deletions(-) create mode 100644 src/ObservableCollections/ICollectionEventDispatcher.cs diff --git a/README.md b/README.md index d9aa598..362dda8 100644 --- a/README.md +++ b/README.md @@ -206,9 +206,9 @@ public partial class DataTable : ComponentBase, IDisposable } ``` -WPF +WPF/Avalonia --- -Because of data binding in WPF, it is important that the collection is Observable. ObservableCollections high-performance `IObservableCollection` cannot be bind to WPF. Call `ToNotifyCollectionChanged()` to convert it to `INotifyCollectionChanged`. Also, although ObservableCollections and Views are thread-safe, the WPF UI does not support change notifications from different threads. `BindingOperations.EnableCollectionSynchronization` to work safely with change notifications from different threads. +Because of data binding in WPF, it is important that the collection is Observable. ObservableCollections high-performance `IObservableCollection` cannot be bind to WPF. Call `ToNotifyCollectionChanged()` to convert it to `INotifyCollectionChanged`. Also, although ObservableCollections and Views are thread-safe, the WPF UI does not support change notifications from different threads. To`ToNotifyCollectionChanged(IColllectionEventDispatcher)` allows multi thread changed. ```csharp // WPF simple sample. @@ -222,9 +222,12 @@ public MainWindow() this.DataContext = this; list = new ObservableList(); - ItemsView = list.CreateView(x => x).ToNotifyCollectionChanged(); - BindingOperations.EnableCollectionSynchronization(ItemsView, new object()); // for ui synchronization safety of viewmodel + // for ui synchronization safety of viewmodel + ItemsView = list.CreateView(x => x).ToNotifyCollectionChanged(SynchronizationContextCollectionEventDispatcher.Current); + + // if collection is changed only from ui-thread, can use this overload + // ItemsView = list.CreateView(x => x).ToNotifyCollectionChanged(); } protected override void OnClosed(EventArgs e) @@ -235,6 +238,22 @@ protected override void OnClosed(EventArgs e) > WPF can not use SortedView because SortedView can not provide sort event to INotifyCollectionChanged. +`SynchronizationContextCollectionEventDispatcher.Current` is default implementation of `IColllectionEventDispatcher`, it is used `SynchronizationContext.Current` for dispatche ui thread. You can create custom `ICollectionEventDispatcher` to use custom dispatcher object. For example use WPF Dispatcher: + +```csharp +public class WpfDispatcherCollection(Dispatcher dispatcher) : ICollectionEventDispatcher +{ + public void Post(CollectionEventDispatcherEventArgs ev) + { + dispatcher.InvokeAsync(() => + { + // notify in dispatcher + ev.Invoke(); + }); + } +} +``` + Unity --- In Unity projects, you can installing `ObservableCollections` with [NugetForUnity](https://github.com/GlitchEnzo/NuGetForUnity). If R3 integration is required, similarly install `ObservableCollections.R3` via NuGetForUnity. diff --git a/sandbox/WpfApp/MainWindow.xaml b/sandbox/WpfApp/MainWindow.xaml index a1fa2f6..67a7270 100644 --- a/sandbox/WpfApp/MainWindow.xaml +++ b/sandbox/WpfApp/MainWindow.xaml @@ -19,6 +19,7 @@ --> +