breaking changes, ISynchronizedView<T> -> ISynchronizedView<T, TView>
This commit is contained in:
parent
bd7cc350f2
commit
73c5b8e83e
@ -35,7 +35,7 @@ namespace ObservableCollections
|
|||||||
public interface ISynchronizedView<T, TView> : IReadOnlyCollection<TView>, IDisposable
|
public interface ISynchronizedView<T, TView> : IReadOnlyCollection<TView>, IDisposable
|
||||||
{
|
{
|
||||||
object SyncRoot { get; }
|
object SyncRoot { get; }
|
||||||
ISynchronizedViewFilter<T> Filter { get; }
|
ISynchronizedViewFilter<T, TView> Filter { get; }
|
||||||
IEnumerable<(T Value, TView View)> Filtered { get; }
|
IEnumerable<(T Value, TView View)> Filtered { get; }
|
||||||
IEnumerable<(T Value, TView View)> Unfiltered { get; }
|
IEnumerable<(T Value, TView View)> Unfiltered { get; }
|
||||||
int UnfilteredCount { get; }
|
int UnfilteredCount { get; }
|
||||||
@ -44,7 +44,7 @@ namespace ObservableCollections
|
|||||||
event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
||||||
event Action<NotifyCollectionChangedAction>? CollectionStateChanged;
|
event Action<NotifyCollectionChangedAction>? CollectionStateChanged;
|
||||||
|
|
||||||
void AttachFilter(ISynchronizedViewFilter<T> filter);
|
void AttachFilter(ISynchronizedViewFilter<T, TView> filter);
|
||||||
void ResetFilter();
|
void ResetFilter();
|
||||||
ISynchronizedViewList<TView> ToViewList();
|
ISynchronizedViewList<TView> ToViewList();
|
||||||
NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged();
|
NotifyCollectionChangedSynchronizedViewList<TView> ToNotifyCollectionChanged();
|
||||||
|
@ -1,24 +1,38 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Specialized;
|
|
||||||
|
|
||||||
namespace ObservableCollections
|
namespace ObservableCollections
|
||||||
{
|
{
|
||||||
|
// Obsolete...
|
||||||
|
[Obsolete("this interface is obsoleted. Use ISynchronizedViewFilter<T, TView> instead.")]
|
||||||
public interface ISynchronizedViewFilter<T>
|
public interface ISynchronizedViewFilter<T>
|
||||||
{
|
{
|
||||||
bool IsMatch(T value);
|
bool IsMatch(T value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SynchronizedViewFilter<T>(Func<T, bool> isMatch) : ISynchronizedViewFilter<T>
|
public interface ISynchronizedViewFilter<T, TView>
|
||||||
{
|
{
|
||||||
public static readonly ISynchronizedViewFilter<T> Null = new NullViewFilter();
|
bool IsMatch(T value, TView view);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsMatch(T value) => isMatch(value);
|
internal class SynchronizedViewValueOnlyFilter<T, TView>(Func<T, bool> isMatch) : ISynchronizedViewFilter<T, TView>
|
||||||
|
{
|
||||||
|
public bool IsMatch(T value, TView view) => isMatch(value);
|
||||||
|
|
||||||
class NullViewFilter : ISynchronizedViewFilter<T>
|
class NullViewFilter : ISynchronizedViewFilter<T, TView>
|
||||||
{
|
{
|
||||||
public bool IsMatch(T value) => true;
|
public bool IsMatch(T value, TView view) => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class SynchronizedViewFilter<T, TView>(Func<T, TView, bool> isMatch) : ISynchronizedViewFilter<T, TView>
|
||||||
|
{
|
||||||
|
public static readonly ISynchronizedViewFilter<T, TView> Null = new NullViewFilter();
|
||||||
|
|
||||||
|
public bool IsMatch(T value, TView view) => isMatch(value, view);
|
||||||
|
|
||||||
|
class NullViewFilter : ISynchronizedViewFilter<T, TView>
|
||||||
|
{
|
||||||
|
public bool IsMatch(T value, TView view) => true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
readonly ObservableDictionary<TKey, TValue> source;
|
readonly ObservableDictionary<TKey, TValue> source;
|
||||||
readonly Func<KeyValuePair<TKey, TValue>, TView> selector;
|
readonly Func<KeyValuePair<TKey, TValue>, TView> selector;
|
||||||
ISynchronizedViewFilter<KeyValuePair<TKey, TValue>> filter;
|
ISynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView> filter;
|
||||||
readonly Dictionary<TKey, (TValue, TView)> dict;
|
readonly Dictionary<TKey, (TValue, TView)> dict;
|
||||||
int filteredCount;
|
int filteredCount;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>>.Null;
|
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.Null;
|
||||||
this.SyncRoot = new object();
|
this.SyncRoot = new object();
|
||||||
lock (source.SyncRoot)
|
lock (source.SyncRoot)
|
||||||
{
|
{
|
||||||
@ -42,7 +42,7 @@ namespace ObservableCollections
|
|||||||
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
||||||
public event Action<NotifyCollectionChangedAction>? CollectionStateChanged;
|
public event Action<NotifyCollectionChangedAction>? CollectionStateChanged;
|
||||||
|
|
||||||
public ISynchronizedViewFilter<KeyValuePair<TKey, TValue>> Filter
|
public ISynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView> Filter
|
||||||
{
|
{
|
||||||
get { lock (SyncRoot) return filter; }
|
get { lock (SyncRoot) return filter; }
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ namespace ObservableCollections
|
|||||||
this.source.CollectionChanged -= SourceCollectionChanged;
|
this.source.CollectionChanged -= SourceCollectionChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AttachFilter(ISynchronizedViewFilter<KeyValuePair<TKey, TValue>> filter)
|
public void AttachFilter(ISynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView> filter)
|
||||||
{
|
{
|
||||||
if (filter.IsNullFilter())
|
if (filter.IsNullFilter())
|
||||||
{
|
{
|
||||||
@ -89,7 +89,7 @@ namespace ObservableCollections
|
|||||||
foreach (var v in dict)
|
foreach (var v in dict)
|
||||||
{
|
{
|
||||||
var value = new KeyValuePair<TKey, TValue>(v.Key, v.Value.Item1);
|
var value = new KeyValuePair<TKey, TValue>(v.Key, v.Value.Item1);
|
||||||
if (filter.IsMatch(value))
|
if (filter.IsMatch(value, v.Value.Item2))
|
||||||
{
|
{
|
||||||
filteredCount++;
|
filteredCount++;
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>>.Null;
|
this.filter = SynchronizedViewFilter<KeyValuePair<TKey, TValue>, TView>.Null;
|
||||||
this.filteredCount = dict.Count;
|
this.filteredCount = dict.Count;
|
||||||
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<KeyValuePair<TKey, TValue>, TView>(NotifyCollectionChangedAction.Reset, true));
|
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<KeyValuePair<TKey, TValue>, TView>(NotifyCollectionChangedAction.Reset, true));
|
||||||
}
|
}
|
||||||
@ -131,7 +131,7 @@ namespace ObservableCollections
|
|||||||
foreach (var item in dict)
|
foreach (var item in dict)
|
||||||
{
|
{
|
||||||
var v = (new KeyValuePair<TKey, TValue>(item.Key, item.Value.Item1), item.Value.Item2);
|
var v = (new KeyValuePair<TKey, TValue>(item.Key, item.Value.Item1), item.Value.Item2);
|
||||||
if (filter.IsMatch(v.Item1))
|
if (filter.IsMatch(v))
|
||||||
{
|
{
|
||||||
yield return v.Item2;
|
yield return v.Item2;
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ namespace ObservableCollections
|
|||||||
foreach (var item in dict)
|
foreach (var item in dict)
|
||||||
{
|
{
|
||||||
var v = (new KeyValuePair<TKey, TValue>(item.Key, item.Value.Item1), item.Value.Item2);
|
var v = (new KeyValuePair<TKey, TValue>(item.Key, item.Value.Item1), item.Value.Item2);
|
||||||
if (filter.IsMatch(v.Item1))
|
if (filter.IsMatch(v))
|
||||||
{
|
{
|
||||||
yield return v;
|
yield return v;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
sealed class View<TView> : ISynchronizedView<T, TView>
|
sealed class View<TView> : ISynchronizedView<T, TView>
|
||||||
{
|
{
|
||||||
public ISynchronizedViewFilter<T> Filter
|
public ISynchronizedViewFilter<T, TView> Filter
|
||||||
{
|
{
|
||||||
get { lock (SyncRoot) return filter; }
|
get { lock (SyncRoot) return filter; }
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@ namespace ObservableCollections
|
|||||||
readonly Dictionary<T, (T, TView)> dict;
|
readonly Dictionary<T, (T, TView)> dict;
|
||||||
int filteredCount;
|
int filteredCount;
|
||||||
|
|
||||||
ISynchronizedViewFilter<T> filter;
|
ISynchronizedViewFilter<T, TView> filter;
|
||||||
|
|
||||||
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
||||||
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
||||||
@ -39,7 +39,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.SyncRoot = new object();
|
this.SyncRoot = new object();
|
||||||
lock (source.SyncRoot)
|
lock (source.SyncRoot)
|
||||||
{
|
{
|
||||||
@ -71,7 +71,7 @@ namespace ObservableCollections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AttachFilter(ISynchronizedViewFilter<T> filter)
|
public void AttachFilter(ISynchronizedViewFilter<T, TView> filter)
|
||||||
{
|
{
|
||||||
if (filter.IsNullFilter())
|
if (filter.IsNullFilter())
|
||||||
{
|
{
|
||||||
@ -85,7 +85,7 @@ namespace ObservableCollections
|
|||||||
this.filteredCount = 0;
|
this.filteredCount = 0;
|
||||||
foreach (var (_, (value, view)) in dict)
|
foreach (var (_, (value, view)) in dict)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(value))
|
if (filter.IsMatch(value, view))
|
||||||
{
|
{
|
||||||
filteredCount++;
|
filteredCount++;
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.filteredCount = dict.Count;
|
this.filteredCount = dict.Count;
|
||||||
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in dict)
|
foreach (var item in dict)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Value.Item1))
|
if (filter.IsMatch(item.Value))
|
||||||
{
|
{
|
||||||
yield return item.Value.Item2;
|
yield return item.Value.Item2;
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in dict)
|
foreach (var item in dict)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Value.Item1))
|
if (filter.IsMatch(item.Value))
|
||||||
{
|
{
|
||||||
yield return item.Value;
|
yield return item.Value;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
internal sealed class View<TView> : ISynchronizedView<T, TView>, IWritableSynchronizedView<T, TView>
|
internal sealed class View<TView> : ISynchronizedView<T, TView>, IWritableSynchronizedView<T, TView>
|
||||||
{
|
{
|
||||||
public ISynchronizedViewFilter<T> Filter
|
public ISynchronizedViewFilter<T, TView> Filter
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@ -61,7 +61,7 @@ namespace ObservableCollections
|
|||||||
internal readonly List<(T, TView)> list; // unsafe, be careful to use
|
internal readonly List<(T, TView)> list; // unsafe, be careful to use
|
||||||
int filteredCount;
|
int filteredCount;
|
||||||
|
|
||||||
ISynchronizedViewFilter<T> filter;
|
ISynchronizedViewFilter<T, TView> filter;
|
||||||
|
|
||||||
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
||||||
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
||||||
@ -73,7 +73,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.SyncRoot = new object();
|
this.SyncRoot = new object();
|
||||||
lock (source.SyncRoot)
|
lock (source.SyncRoot)
|
||||||
{
|
{
|
||||||
@ -105,7 +105,7 @@ namespace ObservableCollections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AttachFilter(ISynchronizedViewFilter<T> filter)
|
public void AttachFilter(ISynchronizedViewFilter<T, TView> filter)
|
||||||
{
|
{
|
||||||
if (filter.IsNullFilter())
|
if (filter.IsNullFilter())
|
||||||
{
|
{
|
||||||
@ -119,7 +119,7 @@ namespace ObservableCollections
|
|||||||
this.filteredCount = 0;
|
this.filteredCount = 0;
|
||||||
for (var i = 0; i < list.Count; i++)
|
for (var i = 0; i < list.Count; i++)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(list[i].Item1))
|
if (filter.IsMatch(list[i]))
|
||||||
{
|
{
|
||||||
filteredCount++;
|
filteredCount++;
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.filteredCount = list.Count;
|
this.filteredCount = list.Count;
|
||||||
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Item1))
|
if (filter.IsMatch(item))
|
||||||
{
|
{
|
||||||
yield return item.Item2;
|
yield return item.Item2;
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Item1))
|
if (filter.IsMatch(item))
|
||||||
{
|
{
|
||||||
yield return item;
|
yield return item;
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ namespace ObservableCollections
|
|||||||
var view = selector(item);
|
var view = selector(item);
|
||||||
views.Span[i] = view;
|
views.Span[i] = view;
|
||||||
valueViews.Span[i] = (item, view);
|
valueViews.Span[i] = (item, view);
|
||||||
var isMatch = matches.Span[i] = Filter.IsMatch(item);
|
var isMatch = matches.Span[i] = Filter.IsMatch(item, view);
|
||||||
if (isMatch)
|
if (isMatch)
|
||||||
{
|
{
|
||||||
filteredCount++; // increment in this process
|
filteredCount++; // increment in this process
|
||||||
@ -271,7 +271,7 @@ namespace ObservableCollections
|
|||||||
var item = list[i];
|
var item = list[i];
|
||||||
values.Span[j] = item.Item1;
|
values.Span[j] = item.Item1;
|
||||||
views.Span[j] = item.Item2;
|
views.Span[j] = item.Item2;
|
||||||
var isMatch = matches.Span[j] = Filter.IsMatch(item.Item1);
|
var isMatch = matches.Span[j] = Filter.IsMatch(item);
|
||||||
if (isMatch)
|
if (isMatch)
|
||||||
{
|
{
|
||||||
filteredCount--; // decrement in this process
|
filteredCount--; // decrement in this process
|
||||||
|
@ -22,7 +22,7 @@ namespace ObservableCollections
|
|||||||
protected readonly Queue<(T, TView)> queue;
|
protected readonly Queue<(T, TView)> queue;
|
||||||
int filteredCount;
|
int filteredCount;
|
||||||
|
|
||||||
ISynchronizedViewFilter<T> filter;
|
ISynchronizedViewFilter<T, TView> filter;
|
||||||
|
|
||||||
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
||||||
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
||||||
@ -30,7 +30,7 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public object SyncRoot { get; }
|
public object SyncRoot { get; }
|
||||||
|
|
||||||
public ISynchronizedViewFilter<T> Filter
|
public ISynchronizedViewFilter<T, TView> Filter
|
||||||
{
|
{
|
||||||
get { lock (SyncRoot) return filter; }
|
get { lock (SyncRoot) return filter; }
|
||||||
}
|
}
|
||||||
@ -39,7 +39,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.SyncRoot = new object();
|
this.SyncRoot = new object();
|
||||||
lock (source.SyncRoot)
|
lock (source.SyncRoot)
|
||||||
{
|
{
|
||||||
@ -71,7 +71,7 @@ namespace ObservableCollections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AttachFilter(ISynchronizedViewFilter<T> filter)
|
public void AttachFilter(ISynchronizedViewFilter<T, TView> filter)
|
||||||
{
|
{
|
||||||
if (filter.IsNullFilter())
|
if (filter.IsNullFilter())
|
||||||
{
|
{
|
||||||
@ -85,7 +85,7 @@ namespace ObservableCollections
|
|||||||
this.filteredCount = 0;
|
this.filteredCount = 0;
|
||||||
foreach (var (value, view) in queue)
|
foreach (var (value, view) in queue)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(value))
|
if (filter.IsMatch(value, view))
|
||||||
{
|
{
|
||||||
filteredCount++;
|
filteredCount++;
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.filteredCount = queue.Count;
|
this.filteredCount = queue.Count;
|
||||||
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in queue)
|
foreach (var item in queue)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Item1))
|
if (filter.IsMatch(item))
|
||||||
{
|
{
|
||||||
yield return item.Item2;
|
yield return item.Item2;
|
||||||
}
|
}
|
||||||
@ -143,7 +143,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in queue)
|
foreach (var item in queue)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Item1))
|
if (filter.IsMatch(item))
|
||||||
{
|
{
|
||||||
yield return item;
|
yield return item;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ namespace ObservableCollections
|
|||||||
// used with ObservableFixedSizeRingBuffer
|
// used with ObservableFixedSizeRingBuffer
|
||||||
internal sealed class View<TView> : ISynchronizedView<T, TView>
|
internal sealed class View<TView> : ISynchronizedView<T, TView>
|
||||||
{
|
{
|
||||||
public ISynchronizedViewFilter<T> Filter
|
public ISynchronizedViewFilter<T, TView> Filter
|
||||||
{
|
{
|
||||||
get { lock (SyncRoot) return filter; }
|
get { lock (SyncRoot) return filter; }
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ namespace ObservableCollections
|
|||||||
readonly RingBuffer<(T, TView)> ringBuffer;
|
readonly RingBuffer<(T, TView)> ringBuffer;
|
||||||
int filteredCount;
|
int filteredCount;
|
||||||
|
|
||||||
ISynchronizedViewFilter<T> filter;
|
ISynchronizedViewFilter<T, TView> filter;
|
||||||
|
|
||||||
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
||||||
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
||||||
@ -40,7 +40,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.SyncRoot = new object();
|
this.SyncRoot = new object();
|
||||||
lock (source.SyncRoot)
|
lock (source.SyncRoot)
|
||||||
{
|
{
|
||||||
@ -72,7 +72,7 @@ namespace ObservableCollections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AttachFilter(ISynchronizedViewFilter<T> filter)
|
public void AttachFilter(ISynchronizedViewFilter<T, TView> filter)
|
||||||
{
|
{
|
||||||
if (filter.IsNullFilter())
|
if (filter.IsNullFilter())
|
||||||
{
|
{
|
||||||
@ -87,7 +87,7 @@ namespace ObservableCollections
|
|||||||
for (var i = 0; i < ringBuffer.Count; i++)
|
for (var i = 0; i < ringBuffer.Count; i++)
|
||||||
{
|
{
|
||||||
var (value, view) = ringBuffer[i];
|
var (value, view) = ringBuffer[i];
|
||||||
if (filter.IsMatch(value))
|
if (filter.IsMatch(value, view))
|
||||||
{
|
{
|
||||||
filteredCount++;
|
filteredCount++;
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.filteredCount = ringBuffer.Count;
|
this.filteredCount = ringBuffer.Count;
|
||||||
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in ringBuffer)
|
foreach (var item in ringBuffer)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Item1))
|
if (filter.IsMatch(item))
|
||||||
{
|
{
|
||||||
yield return item.Item2;
|
yield return item.Item2;
|
||||||
}
|
}
|
||||||
@ -151,7 +151,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in ringBuffer)
|
foreach (var item in ringBuffer)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Item1))
|
if (filter.IsMatch(item))
|
||||||
{
|
{
|
||||||
yield return item;
|
yield return item;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ namespace ObservableCollections
|
|||||||
protected readonly Stack<(T, TView)> stack;
|
protected readonly Stack<(T, TView)> stack;
|
||||||
int filteredCount;
|
int filteredCount;
|
||||||
|
|
||||||
ISynchronizedViewFilter<T> filter;
|
ISynchronizedViewFilter<T, TView> filter;
|
||||||
|
|
||||||
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
public event NotifyViewChangedEventHandler<T, TView>? ViewChanged;
|
||||||
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
public event Action<RejectedViewChangedAction, int, int>? RejectedViewChanged;
|
||||||
@ -29,7 +29,7 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
public object SyncRoot { get; }
|
public object SyncRoot { get; }
|
||||||
|
|
||||||
public ISynchronizedViewFilter<T> Filter
|
public ISynchronizedViewFilter<T, TView> Filter
|
||||||
{
|
{
|
||||||
get { lock (SyncRoot) return filter; }
|
get { lock (SyncRoot) return filter; }
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.SyncRoot = new object();
|
this.SyncRoot = new object();
|
||||||
lock (source.SyncRoot)
|
lock (source.SyncRoot)
|
||||||
{
|
{
|
||||||
@ -70,7 +70,7 @@ namespace ObservableCollections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AttachFilter(ISynchronizedViewFilter<T> filter)
|
public void AttachFilter(ISynchronizedViewFilter<T, TView> filter)
|
||||||
{
|
{
|
||||||
if (filter.IsNullFilter())
|
if (filter.IsNullFilter())
|
||||||
{
|
{
|
||||||
@ -84,7 +84,7 @@ namespace ObservableCollections
|
|||||||
this.filteredCount = 0;
|
this.filteredCount = 0;
|
||||||
foreach (var (value, view) in stack)
|
foreach (var (value, view) in stack)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(value))
|
if (filter.IsMatch(value, view))
|
||||||
{
|
{
|
||||||
filteredCount++;
|
filteredCount++;
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
this.filter = SynchronizedViewFilter<T>.Null;
|
this.filter = SynchronizedViewFilter<T, TView>.Null;
|
||||||
this.filteredCount = stack.Count;
|
this.filteredCount = stack.Count;
|
||||||
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
ViewChanged?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset, true));
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in stack)
|
foreach (var item in stack)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Item1))
|
if (filter.IsMatch(item))
|
||||||
{
|
{
|
||||||
yield return item.Item2;
|
yield return item.Item2;
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
foreach (var item in stack)
|
foreach (var item in stack)
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Item1))
|
if (filter.IsMatch(item))
|
||||||
{
|
{
|
||||||
yield return item;
|
yield return item;
|
||||||
}
|
}
|
||||||
|
@ -86,12 +86,22 @@ namespace ObservableCollections
|
|||||||
{
|
{
|
||||||
public static void AttachFilter<T, TView>(this ISynchronizedView<T, TView> source, Func<T, bool> filter)
|
public static void AttachFilter<T, TView>(this ISynchronizedView<T, TView> source, Func<T, bool> filter)
|
||||||
{
|
{
|
||||||
source.AttachFilter(new SynchronizedViewFilter<T>(filter));
|
source.AttachFilter(new SynchronizedViewValueOnlyFilter<T, TView>(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsNullFilter<T>(this ISynchronizedViewFilter<T> filter)
|
public static void AttachFilter<T, TView>(this ISynchronizedView<T, TView> source, Func<T, TView, bool> filter)
|
||||||
{
|
{
|
||||||
return filter == SynchronizedViewFilter<T>.Null;
|
source.AttachFilter(new SynchronizedViewFilter<T, TView>(filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsNullFilter<T, TView>(this ISynchronizedViewFilter<T, TView> filter)
|
||||||
|
{
|
||||||
|
return filter == SynchronizedViewFilter<T, TView>.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool IsMatch<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T, TView) item)
|
||||||
|
{
|
||||||
|
return filter.IsMatch(item.Item1, item.Item2);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void InvokeOnAdd<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, Action<RejectedViewChangedAction, int, int>? ev2, (T value, TView view) value, int index)
|
internal static void InvokeOnAdd<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, Action<RejectedViewChangedAction, int, int>? ev2, (T value, TView view) value, int index)
|
||||||
@ -101,7 +111,7 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
internal static void InvokeOnAdd<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, Action<RejectedViewChangedAction, int, int>? ev2, T value, TView view, int index)
|
internal static void InvokeOnAdd<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, Action<RejectedViewChangedAction, int, int>? ev2, T value, TView view, int index)
|
||||||
{
|
{
|
||||||
var isMatch = collection.Filter.IsMatch(value);
|
var isMatch = collection.Filter.IsMatch(value, view);
|
||||||
if (isMatch)
|
if (isMatch)
|
||||||
{
|
{
|
||||||
filteredCount++;
|
filteredCount++;
|
||||||
@ -144,7 +154,7 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
internal static void InvokeOnRemove<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, Action<RejectedViewChangedAction, int, int>? ev2, T value, TView view, int oldIndex)
|
internal static void InvokeOnRemove<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, Action<RejectedViewChangedAction, int, int>? ev2, T value, TView view, int oldIndex)
|
||||||
{
|
{
|
||||||
var isMatch = collection.Filter.IsMatch(value);
|
var isMatch = collection.Filter.IsMatch(value, view);
|
||||||
if (isMatch)
|
if (isMatch)
|
||||||
{
|
{
|
||||||
filteredCount--;
|
filteredCount--;
|
||||||
@ -188,7 +198,7 @@ namespace ObservableCollections
|
|||||||
internal static void InvokeOnMove<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, Action<RejectedViewChangedAction, int, int>? ev2, T value, TView view, int index, int oldIndex)
|
internal static void InvokeOnMove<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, Action<RejectedViewChangedAction, int, int>? ev2, T value, TView view, int index, int oldIndex)
|
||||||
{
|
{
|
||||||
// move does not changes filtered-count
|
// move does not changes filtered-count
|
||||||
var isMatch = collection.Filter.IsMatch(value);
|
var isMatch = collection.Filter.IsMatch(value, view);
|
||||||
if (isMatch)
|
if (isMatch)
|
||||||
{
|
{
|
||||||
ev?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Move, true, newItem: (value, view), newStartingIndex: index, oldStartingIndex: oldIndex));
|
ev?.Invoke(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Move, true, newItem: (value, view), newStartingIndex: index, oldStartingIndex: oldIndex));
|
||||||
@ -206,8 +216,8 @@ namespace ObservableCollections
|
|||||||
|
|
||||||
internal static void InvokeOnReplace<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, T value, TView view, T oldValue, TView oldView, int index, int oldIndex = -1)
|
internal static void InvokeOnReplace<T, TView>(this ISynchronizedView<T, TView> collection, ref int filteredCount, NotifyViewChangedEventHandler<T, TView>? ev, T value, TView view, T oldValue, TView oldView, int index, int oldIndex = -1)
|
||||||
{
|
{
|
||||||
var oldMatched = collection.Filter.IsMatch(oldValue);
|
var oldMatched = collection.Filter.IsMatch(oldValue, oldView);
|
||||||
var newMatched = collection.Filter.IsMatch(value);
|
var newMatched = collection.Filter.IsMatch(value, view);
|
||||||
var bothMatched = oldMatched && newMatched;
|
var bothMatched = oldMatched && newMatched;
|
||||||
|
|
||||||
if (bothMatched)
|
if (bothMatched)
|
||||||
|
@ -54,7 +54,7 @@ internal sealed class FiltableSynchronizedViewList<T, TView> : NotifyCollectionC
|
|||||||
{
|
{
|
||||||
foreach (var item in parent.Unfiltered) // use Unfiltered
|
foreach (var item in parent.Unfiltered) // use Unfiltered
|
||||||
{
|
{
|
||||||
if (filter.IsMatch(item.Value))
|
if (filter.IsMatch(item))
|
||||||
{
|
{
|
||||||
yield return (index, item.View);
|
yield return (index, item.View);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user