From 18aa9e45af0fe83d32b037fe045f93c582199cd7 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 15 Feb 2024 14:01:48 +0900 Subject: [PATCH] Change the INotifyCollectionChaneged to IE from IE<(T, View)> --- .../IObservableCollection.cs | 5 +- .../Internal/FreezedView.cs | 14 +++- ...NotifyCollectionChangedSynchronizedView.cs | 67 +++++++++++-------- .../Internal/SortedView.cs | 10 ++- .../Internal/SortedViewViewComparer.cs | 9 ++- .../ObservableCollections.csproj | 4 +- .../ObservableDictionary.Views.cs | 9 ++- .../ObservableHashSet.Views.cs | 7 +- .../ObservableList.Views.cs | 11 ++- .../ObservableQueue.Views.cs | 7 +- .../ObservableRingBuffer.Views.cs | 7 +- .../ObservableStack.Views.cs | 7 +- 12 files changed, 109 insertions(+), 48 deletions(-) diff --git a/src/ObservableCollections/IObservableCollection.cs b/src/ObservableCollections/IObservableCollection.cs index abc38b5..ca9d4de 100644 --- a/src/ObservableCollections/IObservableCollection.cs +++ b/src/ObservableCollections/IObservableCollection.cs @@ -24,13 +24,14 @@ public interface IFreezedCollection public interface ISynchronizedView : IReadOnlyCollection<(T Value, TView View)>, IDisposable { object SyncRoot { get; } + ISynchronizedViewFilter CurrentFilter { get; } event NotifyCollectionChangedEventHandler? RoutingCollectionChanged; event Action? CollectionStateChanged; void AttachFilter(ISynchronizedViewFilter filter, bool invokeAddEventForInitialElements = false); void ResetFilter(Action? resetAction); - INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged(); + INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged(); } public interface ISortableSynchronizedView : ISynchronizedView @@ -44,7 +45,7 @@ public interface ISortableSynchronizedView : ISynchronizedView : ISynchronizedView, INotifyCollectionChanged, INotifyPropertyChanged + public interface INotifyCollectionChangedSynchronizedView : IReadOnlyCollection, INotifyCollectionChanged, INotifyPropertyChanged { } diff --git a/src/ObservableCollections/Internal/FreezedView.cs b/src/ObservableCollections/Internal/FreezedView.cs index f9cd98a..1fc1cfc 100644 --- a/src/ObservableCollections/Internal/FreezedView.cs +++ b/src/ObservableCollections/Internal/FreezedView.cs @@ -15,6 +15,11 @@ internal sealed class FreezedView : ISynchronizedView ISynchronizedViewFilter filter; + public ISynchronizedViewFilter CurrentFilter + { + get { lock (SyncRoot) return filter; } + } + public event Action? CollectionStateChanged; public event NotifyCollectionChangedEventHandler? RoutingCollectionChanged; @@ -107,7 +112,7 @@ public void Dispose() } - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { return new NotifyCollectionChangedSynchronizedView(this); } @@ -119,6 +124,11 @@ internal sealed class FreezedSortableView : ISortableSynchronizedView< ISynchronizedViewFilter filter; + public ISynchronizedViewFilter CurrentFilter + { + get { lock (SyncRoot) return filter; } + } + public event Action? CollectionStateChanged; public event NotifyCollectionChangedEventHandler? RoutingCollectionChanged; @@ -206,7 +216,7 @@ public void Sort(IComparer viewComparer) Array.Sort(array, new TViewComparer(viewComparer)); } - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { return new NotifyCollectionChangedSynchronizedView(this); } diff --git a/src/ObservableCollections/Internal/NotifyCollectionChangedSynchronizedView.cs b/src/ObservableCollections/Internal/NotifyCollectionChangedSynchronizedView.cs index 25efb63..eaf1cb4 100644 --- a/src/ObservableCollections/Internal/NotifyCollectionChangedSynchronizedView.cs +++ b/src/ObservableCollections/Internal/NotifyCollectionChangedSynchronizedView.cs @@ -6,38 +6,20 @@ namespace ObservableCollections.Internal { - internal class NotifyCollectionChangedSynchronizedView : INotifyCollectionChangedSynchronizedView + internal class NotifyCollectionChangedSynchronizedView : + INotifyCollectionChangedSynchronizedView, + ISynchronizedViewFilter { + static readonly PropertyChangedEventArgs CountPropertyChangedEventArgs = new("Count"); + readonly ISynchronizedView parent; - static readonly PropertyChangedEventArgs CountPropertyChangedEventArgs = new PropertyChangedEventArgs("Count"); public NotifyCollectionChangedSynchronizedView(ISynchronizedView parent) { this.parent = parent; - this.parent.RoutingCollectionChanged += Parent_RoutingCollectionChanged; + parent.AttachFilter(this); } - private void Parent_RoutingCollectionChanged(in NotifyCollectionChangedEventArgs e) - { - CollectionChanged?.Invoke(this, e.ToStandardEventArgs()); - - switch (e.Action) - { - // add, remove, reset will change the count. - case NotifyCollectionChangedAction.Add: - case NotifyCollectionChangedAction.Remove: - case NotifyCollectionChangedAction.Reset: - PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs); - break; - case NotifyCollectionChangedAction.Replace: - case NotifyCollectionChangedAction.Move: - default: - break; - } - } - - public object SyncRoot => parent.SyncRoot; - public int Count => parent.Count; public event NotifyCollectionChangedEventHandler? CollectionChanged; @@ -55,16 +37,43 @@ public event NotifyCollectionChangedEventHandler? RoutingCollectionChanged remove { parent.RoutingCollectionChanged -= value; } } - public void AttachFilter(ISynchronizedViewFilter filter, bool invokeAddEventForCurrentElements = false) => parent.AttachFilter(filter, invokeAddEventForCurrentElements); - public void ResetFilter(Action? resetAction) => parent.ResetFilter(resetAction); - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() => this; public void Dispose() { - this.parent.RoutingCollectionChanged -= Parent_RoutingCollectionChanged; parent.Dispose(); } - public IEnumerator<(T, TView)> GetEnumerator() => parent.GetEnumerator(); + public IEnumerator GetEnumerator() + { + foreach (var (value, view) in parent) + { + yield return view; + } + } + IEnumerator IEnumerable.GetEnumerator() => parent.GetEnumerator(); + + public bool IsMatch(T value, TView view) => parent.CurrentFilter.IsMatch(value, view); + public void WhenTrue(T value, TView view) => parent.CurrentFilter.WhenTrue(value, view); + public void WhenFalse(T value, TView view) => parent.CurrentFilter.WhenFalse(value, view); + + public void OnCollectionChanged(ChangedKind changedKind, T value, TView view, in NotifyCollectionChangedEventArgs eventArgs) + { + parent.CurrentFilter.OnCollectionChanged(changedKind, value, view, in eventArgs); + + switch (changedKind) + { + case ChangedKind.Add: + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, view, eventArgs.NewStartingIndex)); + return; + case ChangedKind.Remove: + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, view, eventArgs.OldStartingIndex)); + break; + case ChangedKind.Move: + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, view, eventArgs.NewStartingIndex, eventArgs.OldStartingIndex)); + break; + default: + throw new ArgumentOutOfRangeException(nameof(changedKind), changedKind, null); + } + } } } \ No newline at end of file diff --git a/src/ObservableCollections/Internal/SortedView.cs b/src/ObservableCollections/Internal/SortedView.cs index 435e483..747d822 100644 --- a/src/ObservableCollections/Internal/SortedView.cs +++ b/src/ObservableCollections/Internal/SortedView.cs @@ -2,13 +2,17 @@ using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; -using System.Linq; namespace ObservableCollections.Internal { internal class SortedView : ISynchronizedView where TKey : notnull { + public ISynchronizedViewFilter CurrentFilter + { + get { lock (SyncRoot) return filter; } + } + readonly IObservableCollection source; readonly Func transform; readonly Func identitySelector; @@ -85,7 +89,7 @@ public void ResetFilter(Action? resetAction) } } - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { lock (SyncRoot) { @@ -192,7 +196,7 @@ private void SourceCollectionChanged(in NotifyCollectionChangedEventArgs e) var view = transform(value); var id = identitySelector(value); list.Add((value, id), (value, view)); - var newIndex = list.IndexOfKey((value, id)); + var newIndex = list.IndexOfKey((value, id)); filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs.Add(value, newIndex)); } diff --git a/src/ObservableCollections/Internal/SortedViewViewComparer.cs b/src/ObservableCollections/Internal/SortedViewViewComparer.cs index 5f91980..ab47dc9 100644 --- a/src/ObservableCollections/Internal/SortedViewViewComparer.cs +++ b/src/ObservableCollections/Internal/SortedViewViewComparer.cs @@ -22,6 +22,11 @@ internal class SortedViewViewComparer : ISynchronizedView CurrentFilter + { + get { lock (SyncRoot) return filter; } + } + public SortedViewViewComparer(IObservableCollection source, Func identitySelector, Func transform, IComparer comparer) { this.source = source; @@ -89,7 +94,7 @@ public void ResetFilter(Action? resetAction) } } - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { lock (SyncRoot) { @@ -146,7 +151,7 @@ private void SourceCollectionChanged(in NotifyCollectionChangedEventArgs e) var id = identitySelector(value); list.Add((view, id), (value, view)); viewMap.Add(id, view); - var index = list.IndexOfKey((view, id)); + var index = list.IndexOfKey((view, id)); filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs.Add(value, index)); } } diff --git a/src/ObservableCollections/ObservableCollections.csproj b/src/ObservableCollections/ObservableCollections.csproj index 8f698d0..b6404b1 100644 --- a/src/ObservableCollections/ObservableCollections.csproj +++ b/src/ObservableCollections/ObservableCollections.csproj @@ -1,9 +1,9 @@  - netstandard2.0;netstandard2.1;net5.0;net6.0 + netstandard2.0;netstandard2.1;net6.0;net8.0 enable - 10.0 + 12.0 disable diff --git a/src/ObservableCollections/ObservableDictionary.Views.cs b/src/ObservableCollections/ObservableDictionary.Views.cs index 0dd794a..ed250e1 100644 --- a/src/ObservableCollections/ObservableDictionary.Views.cs +++ b/src/ObservableCollections/ObservableDictionary.Views.cs @@ -14,7 +14,7 @@ public ISynchronizedView, TView> CreateView(Fu // reverse is no used. return new View(this, transform); } - + class View : ISynchronizedView, TView> { readonly ObservableDictionary source; @@ -39,6 +39,11 @@ public View(ObservableDictionary source, Func>? RoutingCollectionChanged; public event Action? CollectionStateChanged; + public ISynchronizedViewFilter, TView> CurrentFilter + { + get { lock (SyncRoot) return filter; } + } + public int Count { get @@ -91,7 +96,7 @@ public void ResetFilter(Action, TView>? resetAction) } } - public INotifyCollectionChangedSynchronizedView, TView> WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { lock (SyncRoot) { diff --git a/src/ObservableCollections/ObservableHashSet.Views.cs b/src/ObservableCollections/ObservableHashSet.Views.cs index 8223634..3039bef 100644 --- a/src/ObservableCollections/ObservableHashSet.Views.cs +++ b/src/ObservableCollections/ObservableHashSet.Views.cs @@ -16,6 +16,11 @@ public ISynchronizedView CreateView(Func transform, b sealed class View : ISynchronizedView { + public ISynchronizedViewFilter CurrentFilter + { + get { lock (SyncRoot) return filter; } + } + readonly ObservableHashSet source; readonly Func selector; readonly Dictionary dict; @@ -85,7 +90,7 @@ public void ResetFilter(Action? resetAction) } } - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { lock (SyncRoot) { diff --git a/src/ObservableCollections/ObservableList.Views.cs b/src/ObservableCollections/ObservableList.Views.cs index ed95711..8b76849 100644 --- a/src/ObservableCollections/ObservableList.Views.cs +++ b/src/ObservableCollections/ObservableList.Views.cs @@ -16,6 +16,14 @@ public ISynchronizedView CreateView(Func transform, b sealed class View : ISynchronizedView { + public ISynchronizedViewFilter CurrentFilter + { + get + { + lock (SyncRoot) { return filter; } + } + } + readonly ObservableList source; readonly Func selector; readonly bool reverse; @@ -33,7 +41,6 @@ public View(ObservableList source, Func selector, bool reverse) this.source = source; this.selector = selector; this.reverse = reverse; - this.filter = SynchronizedViewFilter.Null; this.SyncRoot = new object(); lock (source.SyncRoot) { @@ -89,7 +96,7 @@ public void ResetFilter(Action? resetAction) } } - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { lock (SyncRoot) { diff --git a/src/ObservableCollections/ObservableQueue.Views.cs b/src/ObservableCollections/ObservableQueue.Views.cs index 5f551b6..bcb9e93 100644 --- a/src/ObservableCollections/ObservableQueue.Views.cs +++ b/src/ObservableCollections/ObservableQueue.Views.cs @@ -28,6 +28,11 @@ class View : ISynchronizedView public object SyncRoot { get; } + public ISynchronizedViewFilter CurrentFilter + { + get { lock (SyncRoot) return filter; } + } + public View(ObservableQueue source, Func selector, bool reverse) { this.source = source; @@ -89,7 +94,7 @@ public void ResetFilter(Action? resetAction) } } - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { lock (SyncRoot) { diff --git a/src/ObservableCollections/ObservableRingBuffer.Views.cs b/src/ObservableCollections/ObservableRingBuffer.Views.cs index 3562549..a0866b4 100644 --- a/src/ObservableCollections/ObservableRingBuffer.Views.cs +++ b/src/ObservableCollections/ObservableRingBuffer.Views.cs @@ -17,6 +17,11 @@ public ISynchronizedView CreateView(Func transform, b // used with ObservableFixedSizeRingBuffer internal sealed class View : ISynchronizedView { + public ISynchronizedViewFilter CurrentFilter + { + get { lock (SyncRoot) return filter; } + } + readonly IObservableCollection source; readonly Func selector; readonly bool reverse; @@ -89,7 +94,7 @@ public void ResetFilter(Action? resetAction) } } - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { lock (SyncRoot) { diff --git a/src/ObservableCollections/ObservableStack.Views.cs b/src/ObservableCollections/ObservableStack.Views.cs index 5175732..a21c1e0 100644 --- a/src/ObservableCollections/ObservableStack.Views.cs +++ b/src/ObservableCollections/ObservableStack.Views.cs @@ -28,6 +28,11 @@ class View : ISynchronizedView public object SyncRoot { get; } + public ISynchronizedViewFilter CurrentFilter + { + get { lock (SyncRoot) return filter; } + } + public View(ObservableStack source, Func selector, bool reverse) { this.source = source; @@ -89,7 +94,7 @@ public void ResetFilter(Action? resetAction) } } - public INotifyCollectionChangedSynchronizedView WithINotifyCollectionChanged() + public INotifyCollectionChangedSynchronizedView ToNotifyCollectionChanged() { lock (SyncRoot) {