Change the INotifyCollectionChaneged to IE<TView> from IE<(T, View)>

This commit is contained in:
hadashiA 2024-02-15 14:01:48 +09:00
parent 43ee6ecb9d
commit e2dcbd804b
12 changed files with 109 additions and 47 deletions

View File

@ -24,13 +24,14 @@ namespace ObservableCollections
public interface ISynchronizedView<T, TView> : IReadOnlyCollection<(T Value, TView View)>, IDisposable
{
object SyncRoot { get; }
ISynchronizedViewFilter<T, TView> CurrentFilter { get; }
event NotifyCollectionChangedEventHandler<T>? RoutingCollectionChanged;
event Action<NotifyCollectionChangedAction>? CollectionStateChanged;
void AttachFilter(ISynchronizedViewFilter<T, TView> filter, bool invokeAddEventForInitialElements = false);
void ResetFilter(Action<T, TView>? resetAction);
INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged();
INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged();
}
public interface ISortableSynchronizedView<T, TView> : ISynchronizedView<T, TView>
@ -44,7 +45,7 @@ namespace ObservableCollections
//{
//}
public interface INotifyCollectionChangedSynchronizedView<T, TView> : ISynchronizedView<T, TView>, INotifyCollectionChanged, INotifyPropertyChanged
public interface INotifyCollectionChangedSynchronizedView<out TView> : IReadOnlyCollection<TView>, INotifyCollectionChanged, INotifyPropertyChanged
{
}

View File

@ -15,6 +15,11 @@ namespace ObservableCollections.Internal
ISynchronizedViewFilter<T, TView> filter;
public ISynchronizedViewFilter<T, TView> CurrentFilter
{
get { lock (SyncRoot) return filter; }
}
public event Action<NotifyCollectionChangedAction>? CollectionStateChanged;
public event NotifyCollectionChangedEventHandler<T>? RoutingCollectionChanged;
@ -107,7 +112,7 @@ namespace ObservableCollections.Internal
}
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
}
@ -119,6 +124,11 @@ namespace ObservableCollections.Internal
ISynchronizedViewFilter<T, TView> filter;
public ISynchronizedViewFilter<T, TView> CurrentFilter
{
get { lock (SyncRoot) return filter; }
}
public event Action<NotifyCollectionChangedAction>? CollectionStateChanged;
public event NotifyCollectionChangedEventHandler<T>? RoutingCollectionChanged;
@ -206,7 +216,7 @@ namespace ObservableCollections.Internal
Array.Sort(array, new TViewComparer(viewComparer));
}
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
return new NotifyCollectionChangedSynchronizedView<T, TView>(this);
}

View File

@ -6,38 +6,20 @@ using System.ComponentModel;
namespace ObservableCollections.Internal
{
internal class NotifyCollectionChangedSynchronizedView<T, TView> : INotifyCollectionChangedSynchronizedView<T, TView>
internal class NotifyCollectionChangedSynchronizedView<T, TView> :
INotifyCollectionChangedSynchronizedView<TView>,
ISynchronizedViewFilter<T, TView>
{
static readonly PropertyChangedEventArgs CountPropertyChangedEventArgs = new("Count");
readonly ISynchronizedView<T, TView> parent;
static readonly PropertyChangedEventArgs CountPropertyChangedEventArgs = new PropertyChangedEventArgs("Count");
public NotifyCollectionChangedSynchronizedView(ISynchronizedView<T, TView> parent)
{
this.parent = parent;
this.parent.RoutingCollectionChanged += Parent_RoutingCollectionChanged;
parent.AttachFilter(this);
}
private void Parent_RoutingCollectionChanged(in NotifyCollectionChangedEventArgs<T> 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 @@ namespace ObservableCollections.Internal
remove { parent.RoutingCollectionChanged -= value; }
}
public void AttachFilter(ISynchronizedViewFilter<T, TView> filter, bool invokeAddEventForCurrentElements = false) => parent.AttachFilter(filter, invokeAddEventForCurrentElements);
public void ResetFilter(Action<T, TView>? resetAction) => parent.ResetFilter(resetAction);
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged() => this;
public void Dispose()
{
this.parent.RoutingCollectionChanged -= Parent_RoutingCollectionChanged;
parent.Dispose();
}
public IEnumerator<(T, TView)> GetEnumerator() => parent.GetEnumerator();
public IEnumerator<TView> 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<T> 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);
}
}
}
}

View File

@ -2,13 +2,17 @@
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
namespace ObservableCollections.Internal
{
internal class SortedView<T, TKey, TView> : ISynchronizedView<T, TView>
where TKey : notnull
{
public ISynchronizedViewFilter<T, TView> CurrentFilter
{
get { lock (SyncRoot) return filter; }
}
readonly IObservableCollection<T> source;
readonly Func<T, TView> transform;
readonly Func<T, TKey> identitySelector;
@ -85,7 +89,7 @@ namespace ObservableCollections.Internal
}
}
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{
@ -192,7 +196,7 @@ namespace ObservableCollections.Internal
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<T>.Add(value, newIndex));
}

View File

@ -22,6 +22,11 @@ namespace ObservableCollections.Internal
public object SyncRoot { get; } = new object();
public ISynchronizedViewFilter<T, TView> CurrentFilter
{
get { lock (SyncRoot) return filter; }
}
public SortedViewViewComparer(IObservableCollection<T> source, Func<T, TKey> identitySelector, Func<T, TView> transform, IComparer<TView> comparer)
{
this.source = source;
@ -89,7 +94,7 @@ namespace ObservableCollections.Internal
}
}
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{
@ -146,7 +151,7 @@ namespace ObservableCollections.Internal
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<T>.Add(value, index));
}
}

View File

@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net5.0;net6.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<LangVersion>10.0</LangVersion>
<LangVersion>12.0</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<!-- NuGet Packaging -->

View File

@ -14,7 +14,7 @@ namespace ObservableCollections
// reverse is no used.
return new View<TView>(this, transform);
}
class View<TView> : ISynchronizedView<KeyValuePair<TKey, TValue>, TView>
{
readonly ObservableDictionary<TKey, TValue> source;
@ -39,6 +39,11 @@ namespace ObservableCollections
public event NotifyCollectionChangedEventHandler<KeyValuePair<TKey, TValue>>? RoutingCollectionChanged;
public event Action<NotifyCollectionChangedAction>? CollectionStateChanged;
public ISynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView> CurrentFilter
{
get { lock (SyncRoot) return filter; }
}
public int Count
{
get
@ -91,7 +96,7 @@ namespace ObservableCollections
}
}
public INotifyCollectionChangedSynchronizedView<KeyValuePair<TKey, TValue>, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{

View File

@ -16,6 +16,11 @@ namespace ObservableCollections
sealed class View<TView> : ISynchronizedView<T, TView>
{
public ISynchronizedViewFilter<T, TView> CurrentFilter
{
get { lock (SyncRoot) return filter; }
}
readonly ObservableHashSet<T> source;
readonly Func<T, TView> selector;
readonly Dictionary<T, (T, TView)> dict;
@ -85,7 +90,7 @@ namespace ObservableCollections
}
}
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{

View File

@ -16,6 +16,14 @@ namespace ObservableCollections
sealed class View<TView> : ISynchronizedView<T, TView>
{
public ISynchronizedViewFilter<T, TView> CurrentFilter
{
get
{
lock (SyncRoot) { return filter; }
}
}
readonly ObservableList<T> source;
readonly Func<T, TView> selector;
readonly bool reverse;
@ -89,7 +97,7 @@ namespace ObservableCollections
}
}
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{

View File

@ -28,6 +28,11 @@ namespace ObservableCollections
public object SyncRoot { get; }
public ISynchronizedViewFilter<T, TView> CurrentFilter
{
get { lock (SyncRoot) return filter; }
}
public View(ObservableQueue<T> source, Func<T, TView> selector, bool reverse)
{
this.source = source;
@ -89,7 +94,7 @@ namespace ObservableCollections
}
}
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{

View File

@ -17,6 +17,11 @@ namespace ObservableCollections
// used with ObservableFixedSizeRingBuffer
internal sealed class View<TView> : ISynchronizedView<T, TView>
{
public ISynchronizedViewFilter<T, TView> CurrentFilter
{
get { lock (SyncRoot) return filter; }
}
readonly IObservableCollection<T> source;
readonly Func<T, TView> selector;
readonly bool reverse;
@ -89,7 +94,7 @@ namespace ObservableCollections
}
}
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{

View File

@ -28,6 +28,11 @@ namespace ObservableCollections
public object SyncRoot { get; }
public ISynchronizedViewFilter<T, TView> CurrentFilter
{
get { lock (SyncRoot) return filter; }
}
public View(ObservableStack<T> source, Func<T, TView> selector, bool reverse)
{
this.source = source;
@ -89,7 +94,7 @@ namespace ObservableCollections
}
}
public INotifyCollectionChangedSynchronizedView<T, TView> WithINotifyCollectionChanged()
public INotifyCollectionChangedSynchronizedView<TView> ToNotifyCollectionChanged()
{
lock (SyncRoot)
{