diff --git a/src/ObservableCollections/IObservableCollection.cs b/src/ObservableCollections/IObservableCollection.cs index 474bb8e..efcfae7 100644 --- a/src/ObservableCollections/IObservableCollection.cs +++ b/src/ObservableCollections/IObservableCollection.cs @@ -57,6 +57,10 @@ namespace ObservableCollections //{ //} + public interface ISynchronizedViewList : IReadOnlyList, IDisposable + { + } + public interface INotifyCollectionChangedSynchronizedView : IReadOnlyCollection, INotifyCollectionChanged, INotifyPropertyChanged, IDisposable { } diff --git a/src/ObservableCollections/ISynchronizedViewFilter.cs b/src/ObservableCollections/ISynchronizedViewFilter.cs index 968b286..a2daec2 100644 --- a/src/ObservableCollections/ISynchronizedViewFilter.cs +++ b/src/ObservableCollections/ISynchronizedViewFilter.cs @@ -73,8 +73,8 @@ namespace ObservableCollections { return filter == SynchronizedViewFilter.Null; } - - + + internal static void InvokeOnAdd(this ISynchronizedViewFilter filter, (T value, TView view) value, int index) { filter.InvokeOnAdd(value.value, value.view, index); @@ -139,5 +139,10 @@ namespace ObservableCollections filter.WhenFalse(value, view); } } + + internal static bool IsMatch(this ISynchronizedViewFilter filter, (T, TView) value) + { + return filter.IsMatch(value); + } } } diff --git a/src/ObservableCollections/Internal/NotifyCollectionChangedSynchronizedView.cs b/src/ObservableCollections/Internal/NotifyCollectionChangedSynchronizedView.cs index d28aea7..ee25a44 100644 --- a/src/ObservableCollections/Internal/NotifyCollectionChangedSynchronizedView.cs +++ b/src/ObservableCollections/Internal/NotifyCollectionChangedSynchronizedView.cs @@ -1,11 +1,117 @@ using System; +using System.Buffers; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; +using System.Linq; namespace ObservableCollections.Internal { + internal class SynchronizedViewList : ISynchronizedViewList + { + readonly ISynchronizedView parent; + readonly List listView; + readonly Func selector; + + public SynchronizedViewList(ISynchronizedView parent, Func selector) + { + this.parent = parent; + this.selector = selector; + parent.RoutingCollectionChanged += Parent_RoutingCollectionChanged; // TODO: -= + } + + private void Parent_RoutingCollectionChanged(in NotifyCollectionChangedEventArgs e) + { + // call in parent.lock. + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + if (e.IsSingleItem) + { + // parent.CurrentFilter.IsMatch( + + var item = selector(e.NewItem); + + + + + if (e.NewStartingIndex != -1) + { + listView.Insert(e.NewStartingIndex, selector(e.NewItem)); + } + else // dict is -1 + { + listView.Add(selector(e.NewItem)); + } + } + else + { + if (e.NewStartingIndex != -1) + { + var array = ArrayPool.Shared.Rent(e.NewItems.Length); + try + { + var i = 0; + foreach (var item in e.NewItems) + { + array[i++] = selector(item); + } + + listView.InsertRange(e.NewStartingIndex, array.Take(e.NewItems.Length)); + } + finally + { + ArrayPool.Shared.Return(array, true); + } + } + else + { + foreach (var item in e.NewItems) + { + listView.Add(selector(item)); + } + } + } + break; + case NotifyCollectionChangedAction.Remove: + break; + case NotifyCollectionChangedAction.Replace: + break; + case NotifyCollectionChangedAction.Move: + break; + case NotifyCollectionChangedAction.Reset: + break; + default: + break; + } + + // throw new NotImplementedException(); + } + + public TView this[int index] => throw new NotImplementedException(); + + public int Count => throw new NotImplementedException(); + + public void Dispose() + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + } + + + + internal class NotifyCollectionChangedSynchronizedView : INotifyCollectionChangedSynchronizedView, ISynchronizedViewFilter diff --git a/src/ObservableCollections/ObservableList.Views.cs b/src/ObservableCollections/ObservableList.Views.cs index 03c56dd..549bbcb 100644 --- a/src/ObservableCollections/ObservableList.Views.cs +++ b/src/ObservableCollections/ObservableList.Views.cs @@ -27,7 +27,8 @@ namespace ObservableCollections readonly ObservableList source; readonly Func selector; readonly bool reverse; - internal readonly List<(T, TView)> list; // be careful to use + readonly List<(T, TView)> list; + int filteredCount; ISynchronizedViewFilter filter; @@ -46,6 +47,7 @@ namespace ObservableCollections lock (source.SyncRoot) { this.list = source.list.Select(x => (x, selector(x))).ToList(); + this.filteredCount = list.Count; this.source.CollectionChanged += SourceCollectionChanged; } } @@ -56,7 +58,7 @@ namespace ObservableCollections { lock (SyncRoot) { - return list.Count; + return filteredCount; } } } @@ -160,6 +162,10 @@ namespace ObservableCollections { var v = (e.NewItem, selector(e.NewItem)); list.Add(v); + if (filter.IsMatch(v)) + { + filteredCount++; + } filter.InvokeOnAdd(v, e.NewStartingIndex); } else @@ -169,6 +175,10 @@ namespace ObservableCollections { var v = (item, selector(item)); list.Add(v); + if (filter.IsMatch(v)) + { + filteredCount++; + } filter.InvokeOnAdd(v, i++); } }