Add dedicated event type for ISynchronizedView

This commit is contained in:
hadashiA 2024-02-22 12:51:30 +09:00
parent 8da9587cba
commit 39e2ae5f9d
22 changed files with 285 additions and 285 deletions

View File

@ -65,30 +65,26 @@ class HogeFilter : ISynchronizedViewFilter<int, ViewModel>
view.Value = $"@{value} (odd)"; view.Value = $"@{value} (odd)";
} }
public void OnCollectionChanged( public void OnCollectionChanged(in SynchronizedViewChangedEventArgs<int, ViewModel> eventArgs)
NotifyCollectionChangedAction changedAction,
int value,
ViewModel view,
in NotifyCollectionChangedEventArgs<int> eventArgs)
{ {
switch (changedAction) switch (eventArgs.Action)
{ {
case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Add:
view.Value += " Add"; eventArgs.NewView.Value += " Add";
break; break;
case NotifyCollectionChangedAction.Remove: case NotifyCollectionChangedAction.Remove:
view.Value += " Remove"; eventArgs.OldView.Value += " Remove";
break; break;
case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Move:
view.Value += $" Move {eventArgs.OldStartingIndex} {eventArgs.NewStartingIndex}"; eventArgs.NewView.Value += $" Move {eventArgs.OldViewIndex} {eventArgs.NewViewIndex}";
break; break;
case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Replace:
view.Value += $" Replace {eventArgs.OldStartingIndex} {eventArgs.NewStartingIndex}"; eventArgs.NewView.Value += $" Replace {eventArgs.NewViewIndex}";
break; break;
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
break; break;
default: default:
throw new ArgumentOutOfRangeException(nameof(changedAction), changedAction, null); throw new ArgumentOutOfRangeException(nameof(eventArgs.Action), eventArgs.Action, null);
} }
} }
} }

View File

@ -3,43 +3,52 @@ using System.Collections.Specialized;
namespace ObservableCollections namespace ObservableCollections
{ {
public readonly struct SynchronizedViewChangedEventArgs<T, TView>(
NotifyCollectionChangedAction action,
T newValue = default!,
T oldValue = default!,
TView newView = default!,
TView oldView = default!,
int newViewIndex = -1,
int oldViewIndex = -1)
{
public readonly NotifyCollectionChangedAction Action = action;
public readonly T NewValue = newValue;
public readonly T OldValue = oldValue;
public readonly TView NewView = newView;
public readonly TView OldView = oldView;
public readonly int NewViewIndex = newViewIndex;
public readonly int OldViewIndex = oldViewIndex;
}
public interface ISynchronizedViewFilter<T, TView> public interface ISynchronizedViewFilter<T, TView>
{ {
bool IsMatch(T value, TView view); bool IsMatch(T value, TView view);
void WhenTrue(T value, TView view); void WhenTrue(T value, TView view);
void WhenFalse(T value, TView view); void WhenFalse(T value, TView view);
void OnCollectionChanged(NotifyCollectionChangedAction changedAction, T value, TView view, in NotifyCollectionChangedEventArgs<T> eventArgs); void OnCollectionChanged(in SynchronizedViewChangedEventArgs<T, TView> eventArgs);
} }
public class SynchronizedViewFilter<T, TView> : ISynchronizedViewFilter<T, TView> public class SynchronizedViewFilter<T, TView>(
Func<T, TView, bool> isMatch,
Action<T, TView>? whenTrue,
Action<T, TView>? whenFalse,
Action<SynchronizedViewChangedEventArgs<T, TView>>? onCollectionChanged)
: ISynchronizedViewFilter<T, TView>
{ {
public static readonly ISynchronizedViewFilter<T, TView> Null = new NullViewFilter(); public static readonly ISynchronizedViewFilter<T, TView> Null = new NullViewFilter();
readonly Func<T, TView, bool> isMatch;
readonly Action<T, TView>? whenTrue;
readonly Action<T, TView>? whenFalse;
readonly Action<NotifyCollectionChangedAction, T, TView>? onCollectionChanged;
public SynchronizedViewFilter(Func<T, TView, bool> isMatch, Action<T, TView>? whenTrue, Action<T, TView>? whenFalse, Action<NotifyCollectionChangedAction, T, TView>? onCollectionChanged)
{
this.isMatch = isMatch;
this.whenTrue = whenTrue;
this.whenFalse = whenFalse;
this.onCollectionChanged = onCollectionChanged;
}
public bool IsMatch(T value, TView view) => isMatch(value, view); public bool IsMatch(T value, TView view) => isMatch(value, view);
public void WhenFalse(T value, TView view) => whenFalse?.Invoke(value, view); public void WhenFalse(T value, TView view) => whenFalse?.Invoke(value, view);
public void WhenTrue(T value, TView view) => whenTrue?.Invoke(value, view); public void WhenTrue(T value, TView view) => whenTrue?.Invoke(value, view);
public void OnCollectionChanged(NotifyCollectionChangedAction changedAction, T value, TView view, in NotifyCollectionChangedEventArgs<T> eventArgs) => public void OnCollectionChanged(in SynchronizedViewChangedEventArgs<T, TView> eventArgs) => onCollectionChanged?.Invoke(eventArgs);
onCollectionChanged?.Invoke(changedAction, value, view);
class NullViewFilter : ISynchronizedViewFilter<T, TView> class NullViewFilter : ISynchronizedViewFilter<T, TView>
{ {
public bool IsMatch(T value, TView view) => true; public bool IsMatch(T value, TView view) => true;
public void WhenFalse(T value, TView view) { } public void WhenFalse(T value, TView view) { }
public void WhenTrue(T value, TView view) { } public void WhenTrue(T value, TView view) { }
public void OnCollectionChanged(NotifyCollectionChangedAction changedAction, T value, TView view, in NotifyCollectionChangedEventArgs<T> eventArgs) { } public void OnCollectionChanged(in SynchronizedViewChangedEventArgs<T, TView> eventArgs) { }
} }
} }
@ -55,7 +64,7 @@ namespace ObservableCollections
source.AttachFilter(new SynchronizedViewFilter<T, TView>(isMatch, whenTrue, whenFalse, null)); source.AttachFilter(new SynchronizedViewFilter<T, TView>(isMatch, whenTrue, whenFalse, null));
} }
public static void AttachFilter<T, TView>(this ISynchronizedView<T, TView> source, Func<T, TView, bool> isMatch, Action<T, TView>? whenTrue, Action<T, TView>? whenFalse, Action<NotifyCollectionChangedAction, T, TView>? onCollectionChanged) public static void AttachFilter<T, TView>(this ISynchronizedView<T, TView> source, Func<T, TView, bool> isMatch, Action<T, TView>? whenTrue, Action<T, TView>? whenFalse, Action<SynchronizedViewChangedEventArgs<T, TView>>? onCollectionChanged)
{ {
source.AttachFilter(new SynchronizedViewFilter<T, TView>(isMatch, whenTrue, whenFalse, onCollectionChanged)); source.AttachFilter(new SynchronizedViewFilter<T, TView>(isMatch, whenTrue, whenFalse, onCollectionChanged));
} }
@ -65,12 +74,13 @@ namespace ObservableCollections
return filter == SynchronizedViewFilter<T, TView>.Null; return filter == SynchronizedViewFilter<T, TView>.Null;
} }
internal static void InvokeOnAdd<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value, in NotifyCollectionChangedEventArgs<T> eventArgs)
internal static void InvokeOnAdd<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value, int index)
{ {
InvokeOnAdd(filter, value.value, value.view, eventArgs); filter.InvokeOnAdd(value.value, value.view, index);
} }
internal static void InvokeOnAdd<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view, in NotifyCollectionChangedEventArgs<T> eventArgs) internal static void InvokeOnAdd<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view, int index)
{ {
if (filter.IsMatch(value, view)) if (filter.IsMatch(value, view))
{ {
@ -80,42 +90,42 @@ namespace ObservableCollections
{ {
filter.WhenFalse(value, view); filter.WhenFalse(value, view);
} }
filter.OnCollectionChanged(NotifyCollectionChangedAction.Add, value, view, eventArgs); filter.OnCollectionChanged(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Add, newValue: value, newView: view, newViewIndex: index));
} }
internal static void InvokeOnRemove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value, in NotifyCollectionChangedEventArgs<T> eventArgs) internal static void InvokeOnRemove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value, int oldIndex)
{ {
InvokeOnRemove(filter, value.value, value.view, eventArgs); filter.InvokeOnRemove(value.value, value.view, oldIndex);
} }
internal static void InvokeOnRemove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view, in NotifyCollectionChangedEventArgs<T> eventArgs) internal static void InvokeOnRemove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view, int oldIndex)
{ {
filter.OnCollectionChanged(NotifyCollectionChangedAction.Remove, value, view, eventArgs); filter.OnCollectionChanged(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Remove, oldValue: value, oldView: view, oldViewIndex: oldIndex));
} }
internal static void InvokeOnMove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value, in NotifyCollectionChangedEventArgs<T> eventArgs) internal static void InvokeOnMove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value, int index, int oldIndex)
{ {
InvokeOnMove(filter, value.value, value.view, eventArgs); InvokeOnMove(filter, value.value, value.view, index, oldIndex);
} }
internal static void InvokeOnMove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view, in NotifyCollectionChangedEventArgs<T> eventArgs) internal static void InvokeOnMove<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view, int index, int oldIndex)
{ {
filter.OnCollectionChanged(NotifyCollectionChangedAction.Move, value, view, eventArgs); filter.OnCollectionChanged(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Move, newValue: value, newView: view, newViewIndex: index, oldViewIndex: oldIndex));
} }
internal static void InvokeOnReplace<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value, in NotifyCollectionChangedEventArgs<T> eventArgs) internal static void InvokeOnReplace<T, TView>(this ISynchronizedViewFilter<T, TView> filter, (T value, TView view) value, (T value, TView view) oldValue, int index, int oldIndex = -1)
{ {
InvokeOnReplace(filter, value.value, value.view, eventArgs); filter.InvokeOnReplace(value.value, value.view, oldValue.value, oldValue.view, index, oldIndex);
} }
internal static void InvokeOnReplace<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view, in NotifyCollectionChangedEventArgs<T> eventArgs) internal static void InvokeOnReplace<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view, T oldValue, TView oldView, int index, int oldIndex = -1)
{ {
filter.OnCollectionChanged(NotifyCollectionChangedAction.Replace, value, view, eventArgs); filter.OnCollectionChanged(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Replace, newValue: value, newView: view, oldValue: oldValue, oldView: oldView, newViewIndex: index, oldViewIndex: oldIndex >= 0 ? oldIndex : index));
} }
internal static void InvokeOnReset<T, TView>(this ISynchronizedViewFilter<T, TView> filter, in NotifyCollectionChangedEventArgs<T> eventArgs) internal static void InvokeOnReset<T, TView>(this ISynchronizedViewFilter<T, TView> filter)
{ {
filter.OnCollectionChanged(NotifyCollectionChangedAction.Reset, default!, default!, eventArgs); filter.OnCollectionChanged(new SynchronizedViewChangedEventArgs<T, TView>(NotifyCollectionChangedAction.Reset));
} }
internal static void InvokeOnAttach<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view) internal static void InvokeOnAttach<T, TView>(this ISynchronizedViewFilter<T, TView> filter, T value, TView view)

View File

@ -53,7 +53,7 @@ namespace ObservableCollections.Internal
var (value, view) = list[i]; var (value, view) = list[i];
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<T>.Add(value, i)); filter.InvokeOnAdd(value, view, i);
} }
else else
{ {
@ -161,7 +161,7 @@ namespace ObservableCollections.Internal
var (value, view) = array[i]; var (value, view) = array[i];
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<T>.Add(value, i)); filter.InvokeOnAdd(value, view, i);
} }
else else
{ {

View File

@ -58,18 +58,30 @@ namespace ObservableCollections.Internal
public void WhenTrue(T value, TView view) => currentFilter.WhenTrue(value, view); public void WhenTrue(T value, TView view) => currentFilter.WhenTrue(value, view);
public void WhenFalse(T value, TView view) => currentFilter.WhenFalse(value, view); public void WhenFalse(T value, TView view) => currentFilter.WhenFalse(value, view);
public void OnCollectionChanged(NotifyCollectionChangedAction changedAction, T value, TView view, in NotifyCollectionChangedEventArgs<T> eventArgs) public void OnCollectionChanged(in SynchronizedViewChangedEventArgs<T, TView> args)
{ {
currentFilter.OnCollectionChanged(changedAction, value, view, in eventArgs); currentFilter.OnCollectionChanged(args);
CollectionChanged?.Invoke(this, eventArgs.ToStandardEventArgs());
switch (changedAction) switch (args.Action)
{ {
case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Add:
case NotifyCollectionChangedAction.Remove: CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, args.NewView, args.NewViewIndex));
case NotifyCollectionChangedAction.Reset:
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs); PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
break; break;
case NotifyCollectionChangedAction.Remove:
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, args.OldView, args.OldViewIndex));
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
break;
case NotifyCollectionChangedAction.Reset:
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
PropertyChanged?.Invoke(this, CountPropertyChangedEventArgs);
break;
case NotifyCollectionChangedAction.Replace:
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, args.NewView, args.OldView, args.NewViewIndex));
break;
case NotifyCollectionChangedAction.Move:
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, args.NewView, args.NewViewIndex, args.OldViewIndex));
break;
} }
} }
} }

View File

@ -60,11 +60,12 @@ namespace ObservableCollections.Internal
lock (SyncRoot) lock (SyncRoot)
{ {
this.filter = filter; this.filter = filter;
var i = 0;
foreach (var (_, (value, view)) in list) foreach (var (_, (value, view)) in list)
{ {
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<T>.Add(value, -1)); filter.InvokeOnAdd(value, view, i++);
} }
else else
{ {
@ -134,7 +135,7 @@ namespace ObservableCollections.Internal
var id = identitySelector(value); var id = identitySelector(value);
list.Add((value, id), (value, view)); list.Add((value, id), (value, view));
var index = list.IndexOfKey((value, id)); var index = list.IndexOfKey((value, id));
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<T>.Add(value, index)); filter.InvokeOnAdd(value, view, index);
} }
else else
{ {
@ -144,7 +145,7 @@ namespace ObservableCollections.Internal
var id = identitySelector(value); var id = identitySelector(value);
list.Add((value, id), (value, view)); list.Add((value, id), (value, view));
var index = list.IndexOfKey((value, id)); var index = list.IndexOfKey((value, id));
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<T>.Add(value, index)); filter.InvokeOnAdd(value, view, index);
} }
} }
} }
@ -160,7 +161,7 @@ namespace ObservableCollections.Internal
{ {
var index = list.IndexOfKey(key); var index = list.IndexOfKey(key);
list.RemoveAt(index); list.RemoveAt(index);
filter.InvokeOnRemove(v.Value, v.View, NotifyCollectionChangedEventArgs<T>.Remove(v.Value, index)); filter.InvokeOnRemove(v.Value, v.View, index);
} }
} }
else else
@ -173,7 +174,7 @@ namespace ObservableCollections.Internal
{ {
var index = list.IndexOfKey((value, id)); var index = list.IndexOfKey((value, id));
list.RemoveAt(index); list.RemoveAt(index);
filter.InvokeOnRemove(v.Value, v.View, NotifyCollectionChangedEventArgs<T>.Remove(v.Value, index)); filter.InvokeOnRemove(v.Value, v.View, index);
} }
} }
} }
@ -198,22 +199,24 @@ namespace ObservableCollections.Internal
list.Add((value, id), (value, view)); list.Add((value, id), (value, view));
var newIndex = list.IndexOfKey((value, id)); var newIndex = list.IndexOfKey((value, id));
filter.InvokeOnReplace(value, view, NotifyCollectionChangedEventArgs<T>.Replace(e.NewItem, e.OldItem, newIndex, oldIndex)); filter.InvokeOnReplace((value, view), o, newIndex, oldIndex: oldIndex);
} }
break; break;
case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Move:
{ {
// Move(index change) does not affect sorted list. // Move(index change) does not affect sorted list.
var oldValue = e.OldItem; var oldValue = e.OldItem;
if (list.TryGetValue((oldValue, identitySelector(oldValue)), out var view)) var oldKey = (oldValue, identitySelector(oldValue));
if (list.TryGetValue(oldKey, out var v))
{ {
filter.InvokeOnMove(view, e); var index = list.IndexOfKey(oldKey);
filter.InvokeOnMove(v, index, index);
} }
} }
break; break;
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
list.Clear(); list.Clear();
filter.InvokeOnReset(e); filter.InvokeOnReset();
break; break;
default: default:
break; break;

View File

@ -65,11 +65,12 @@ namespace ObservableCollections.Internal
lock (SyncRoot) lock (SyncRoot)
{ {
this.filter = filter; this.filter = filter;
var i = 0;
foreach (var (_, (value, view)) in list) foreach (var (_, (value, view)) in list)
{ {
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<T>.Add(value, -1)); filter.InvokeOnAdd(value, view, i++);
} }
else else
{ {
@ -141,7 +142,7 @@ namespace ObservableCollections.Internal
list.Add((view, id), (value, view)); list.Add((view, id), (value, view));
viewMap.Add(id, 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)); filter.InvokeOnAdd(value, view, index);
} }
else else
{ {
@ -152,7 +153,7 @@ namespace ObservableCollections.Internal
list.Add((view, id), (value, view)); list.Add((view, id), (value, view));
viewMap.Add(id, 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)); filter.InvokeOnAdd(value, view, index);
} }
} }
break; break;
@ -170,7 +171,7 @@ namespace ObservableCollections.Internal
{ {
var index = list.IndexOfKey(key); var index = list.IndexOfKey(key);
list.RemoveAt(index); list.RemoveAt(index);
filter.InvokeOnRemove(v, NotifyCollectionChangedEventArgs<T>.Remove(v.Value, index)); filter.InvokeOnRemove(v, index);
} }
} }
} }
@ -186,7 +187,7 @@ namespace ObservableCollections.Internal
{ {
var index = list.IndexOfKey((view, id)); var index = list.IndexOfKey((view, id));
list.RemoveAt(index); list.RemoveAt(index);
filter.InvokeOnRemove(v, NotifyCollectionChangedEventArgs<T>.Remove(v.Value, index)); filter.InvokeOnRemove(v, index);
} }
} }
} }
@ -216,24 +217,25 @@ namespace ObservableCollections.Internal
viewMap.Add(id, view); viewMap.Add(id, view);
var index = list.IndexOfKey((view, id)); var index = list.IndexOfKey((view, id));
filter.InvokeOnReplace(value, view, NotifyCollectionChangedEventArgs<T>.Replace(e.NewItem, e.OldItem, index, oldIndex)); filter.InvokeOnReplace(value, view, oldValue, oldView, index, oldIndex);
break; break;
} }
case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Move:
// Move(index change) does not affect soreted dict. // Move(index change) does not affect soreted dict.
{ {
var value = e.OldItem; var value = e.OldItem;
var key = identitySelector(value); var id = identitySelector(value);
if (viewMap.TryGetValue(key, out var view)) if (viewMap.TryGetValue(id, out var view))
{ {
filter.InvokeOnMove(value, view, e); var index = list.IndexOfKey((view, id));
filter.InvokeOnMove(value, view, index, index);
} }
break; break;
} }
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
list.Clear(); list.Clear();
viewMap.Clear(); viewMap.Clear();
filter.InvokeOnReset(e); filter.InvokeOnReset();
break; break;
default: default:
break; break;

View File

@ -42,48 +42,6 @@ namespace ObservableCollections
OldStartingIndex = oldStartingIndex; OldStartingIndex = oldStartingIndex;
} }
public NotifyCollectionChangedEventArgs ToStandardEventArgs()
{
switch (Action)
{
case NotifyCollectionChangedAction.Add:
if (IsSingleItem)
{
return new NotifyCollectionChangedEventArgs(Action, NewItem, NewStartingIndex);
}
else
{
return new NotifyCollectionChangedEventArgs(Action, NewItems.ToArray(), NewStartingIndex);
}
case NotifyCollectionChangedAction.Remove:
if (IsSingleItem)
{
return new NotifyCollectionChangedEventArgs(Action, OldItem, OldStartingIndex);
}
else
{
return new NotifyCollectionChangedEventArgs(Action, OldItems.ToArray(), OldStartingIndex);
}
case NotifyCollectionChangedAction.Replace:
if (IsSingleItem)
{
return new NotifyCollectionChangedEventArgs(Action, NewItem, OldItem, NewStartingIndex);
}
else
{
return new NotifyCollectionChangedEventArgs(Action, NewItems.ToArray(), OldItems.ToArray(), NewStartingIndex);
}
case NotifyCollectionChangedAction.Move:
{
return new NotifyCollectionChangedEventArgs(Action, OldItem, NewStartingIndex, OldStartingIndex);
}
case NotifyCollectionChangedAction.Reset:
return new NotifyCollectionChangedEventArgs(Action);
default:
throw new ArgumentOutOfRangeException();
}
}
public static NotifyCollectionChangedEventArgs<T> Add(T newItem, int newStartingIndex) public static NotifyCollectionChangedEventArgs<T> Add(T newItem, int newStartingIndex)
{ {
return new NotifyCollectionChangedEventArgs<T>(NotifyCollectionChangedAction.Add, true, newItem: newItem, newStartingIndex: newStartingIndex); return new NotifyCollectionChangedEventArgs<T>(NotifyCollectionChangedAction.Add, true, newItem: newItem, newStartingIndex: newStartingIndex);

View File

@ -71,7 +71,7 @@ namespace ObservableCollections
var view = v.Value.Item2; var view = v.Value.Item2;
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<KeyValuePair<TKey, TValue>>.Add(value, -1)); filter.InvokeOnAdd(value, view, -1);
} }
else else
{ {
@ -135,30 +135,30 @@ namespace ObservableCollections
{ {
var v = selector(e.NewItem); var v = selector(e.NewItem);
dict.Add(e.NewItem.Key, (e.NewItem.Value, v)); dict.Add(e.NewItem.Key, (e.NewItem.Value, v));
filter.InvokeOnAdd(new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value), v, e); filter.InvokeOnAdd(e.NewItem, v, -1);
} }
break; break;
case NotifyCollectionChangedAction.Remove: case NotifyCollectionChangedAction.Remove:
{ {
if (dict.Remove(e.OldItem.Key, out var v)) if (dict.Remove(e.OldItem.Key, out var v))
{ {
filter.InvokeOnRemove((new KeyValuePair<TKey, TValue>(e.OldItem.Key, v.Item1), v.Item2), e); filter.InvokeOnRemove(e.OldItem, v.Item2, -1);
} }
} }
break; break;
case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Replace:
{ {
var v = selector(e.NewItem); var v = selector(e.NewItem);
dict.Remove(e.OldItem.Key); dict.Remove(e.OldItem.Key, out var ov);
dict[e.NewItem.Key] = (e.NewItem.Value, v); dict[e.NewItem.Key] = (e.NewItem.Value, v);
filter.InvokeOnReplace(new KeyValuePair<TKey, TValue>(e.NewItem.Key, e.NewItem.Value), v, e); filter.InvokeOnReplace(e.NewItem, v, e.OldItem, ov.Item2, -1);
} }
break; break;
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
{ {
dict.Clear(); dict.Clear();
filter.InvokeOnReset(e); filter.InvokeOnReset();
} }
break; break;
case NotifyCollectionChangedAction.Move: // ObservableDictionary have no Move operation. case NotifyCollectionChangedAction.Move: // ObservableDictionary have no Move operation.

View File

@ -65,7 +65,7 @@ namespace ObservableCollections
{ {
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
filter.InvokeOnAdd((value, view), NotifyCollectionChangedEventArgs<T>.Add(value, -1)); filter.InvokeOnAdd((value, view), -1);
} }
else else
{ {
@ -130,15 +130,16 @@ namespace ObservableCollections
{ {
var v = (e.NewItem, selector(e.NewItem)); var v = (e.NewItem, selector(e.NewItem));
dict.Add(e.NewItem, v); dict.Add(e.NewItem, v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, -1);
} }
else else
{ {
var i = e.NewStartingIndex;
foreach (var item in e.NewItems) foreach (var item in e.NewItems)
{ {
var v = (item, selector(item)); var v = (item, selector(item));
dict.Add(item, v); dict.Add(item, v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, i++);
} }
} }
break; break;
@ -147,7 +148,7 @@ namespace ObservableCollections
{ {
if (dict.Remove(e.OldItem, out var value)) if (dict.Remove(e.OldItem, out var value))
{ {
filter.InvokeOnRemove(value.Item1, value.Item2, e); filter.InvokeOnRemove(value, -1);
} }
} }
else else
@ -156,14 +157,14 @@ namespace ObservableCollections
{ {
if (dict.Remove(item, out var value)) if (dict.Remove(item, out var value))
{ {
filter.InvokeOnRemove(value.Item1, value.Item2, e); filter.InvokeOnRemove(value, -1);
} }
} }
} }
break; break;
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
dict.Clear(); dict.Clear();
filter.InvokeOnReset(e); filter.InvokeOnReset();
break; break;
case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Move:

View File

@ -71,8 +71,7 @@ namespace ObservableCollections
var (value, view) = list[i]; var (value, view) = list[i];
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
var eventArgs = NotifyCollectionChangedEventArgs<T>.Add(value, i); filter.InvokeOnAdd(value, view, i);
filter.InvokeOnAdd(value, view, eventArgs);
} }
else else
{ {
@ -153,15 +152,16 @@ namespace ObservableCollections
{ {
var v = (e.NewItem, selector(e.NewItem)); var v = (e.NewItem, selector(e.NewItem));
list.Add(v); list.Add(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, e.NewStartingIndex);
} }
else else
{ {
var i = e.NewStartingIndex;
foreach (var item in e.NewItems) foreach (var item in e.NewItems)
{ {
var v = (item, selector(item)); var v = (item, selector(item));
list.Add(v); list.Add(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, i++);
} }
} }
} }
@ -172,18 +172,18 @@ namespace ObservableCollections
{ {
var v = (e.NewItem, selector(e.NewItem)); var v = (e.NewItem, selector(e.NewItem));
list.Insert(e.NewStartingIndex, v); list.Insert(e.NewStartingIndex, v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, e.NewStartingIndex);
} }
else else
{ {
// inefficient copy, need refactoring // inefficient copy, need refactoring
var newArray = new (T, TView)[e.NewItems.Length]; var newArray = new (T, TView)[e.NewItems.Length];
var span = e.NewItems; var span = e.NewItems;
for (int i = 0; i < span.Length; i++) for (var i = 0; i < span.Length; i++)
{ {
var v = (span[i], selector(span[i])); var v = (span[i], selector(span[i]));
newArray[i] = v; newArray[i] = v;
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, e.NewStartingIndex + i);
} }
list.InsertRange(e.NewStartingIndex, newArray); list.InsertRange(e.NewStartingIndex, newArray);
} }
@ -194,15 +194,15 @@ namespace ObservableCollections
{ {
var v = list[e.OldStartingIndex]; var v = list[e.OldStartingIndex];
list.RemoveAt(e.OldStartingIndex); list.RemoveAt(e.OldStartingIndex);
filter.InvokeOnRemove(v.Item1, v.Item2, e); filter.InvokeOnRemove(v, e.OldStartingIndex);
} }
else else
{ {
var len = e.OldStartingIndex + e.OldItems.Length; var len = e.OldStartingIndex + e.OldItems.Length;
for (int i = e.OldStartingIndex; i < len; i++) for (var i = e.OldStartingIndex; i < len; i++)
{ {
var v = list[i]; var v = list[i];
filter.InvokeOnRemove(v.Item1, v.Item2, e); filter.InvokeOnRemove(v, e.OldStartingIndex + i);
} }
list.RemoveRange(e.OldStartingIndex, e.OldItems.Length); list.RemoveRange(e.OldStartingIndex, e.OldItems.Length);
@ -212,8 +212,9 @@ namespace ObservableCollections
// ObservableList does not support replace range // ObservableList does not support replace range
{ {
var v = (e.NewItem, selector(e.NewItem)); var v = (e.NewItem, selector(e.NewItem));
var ov = (e.OldItem, selector(e.OldItem));
list[e.NewStartingIndex] = v; list[e.NewStartingIndex] = v;
filter.InvokeOnReplace(v, e); filter.InvokeOnReplace(v, ov, e.NewStartingIndex);
break; break;
} }
case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Move:
@ -222,12 +223,12 @@ namespace ObservableCollections
list.RemoveAt(e.OldStartingIndex); list.RemoveAt(e.OldStartingIndex);
list.Insert(e.NewStartingIndex, removeItem); list.Insert(e.NewStartingIndex, removeItem);
filter.InvokeOnMove(removeItem, e); filter.InvokeOnMove(removeItem, e.NewStartingIndex, e.OldStartingIndex);
} }
break; break;
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
list.Clear(); list.Clear();
filter.InvokeOnReset(e); filter.InvokeOnReset();
break; break;
default: default:
break; break;

View File

@ -68,13 +68,12 @@ namespace ObservableCollections
{ {
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<T>.Add(value, i)); filter.InvokeOnAdd(value, view, i++);
} }
else else
{ {
filter.InvokeOnAttach(value, view); filter.InvokeOnAttach(value, view);
} }
i++;
} }
} }
} }
@ -148,15 +147,16 @@ namespace ObservableCollections
{ {
var v = (e.NewItem, selector(e.NewItem)); var v = (e.NewItem, selector(e.NewItem));
queue.Enqueue(v); queue.Enqueue(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, e.NewStartingIndex);
} }
else else
{ {
var i = e.NewStartingIndex;
foreach (var item in e.NewItems) foreach (var item in e.NewItems)
{ {
var v = (item, selector(item)); var v = (item, selector(item));
queue.Enqueue(v); queue.Enqueue(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, i++);
} }
} }
break; break;
@ -165,7 +165,7 @@ namespace ObservableCollections
if (e.IsSingleItem) if (e.IsSingleItem)
{ {
var v = queue.Dequeue(); var v = queue.Dequeue();
filter.InvokeOnRemove(v.Item1, v.Item2, e); filter.InvokeOnRemove(v.Item1, v.Item2, 0);
} }
else else
{ {
@ -173,13 +173,13 @@ namespace ObservableCollections
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
var v = queue.Dequeue(); var v = queue.Dequeue();
filter.InvokeOnRemove(v.Item1, v.Item2, e); filter.InvokeOnRemove(v.Item1, v.Item2, 0);
} }
} }
break; break;
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
queue.Clear(); queue.Clear();
filter.InvokeOnReset(e); filter.InvokeOnReset();
break; break;
case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Move:

View File

@ -69,7 +69,7 @@ namespace ObservableCollections
var (value, view) = ringBuffer[i]; var (value, view) = ringBuffer[i];
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<T>.Add(value, i)); filter.InvokeOnAdd(value, view, i);
} }
else else
{ {
@ -154,7 +154,7 @@ namespace ObservableCollections
{ {
var v = (e.NewItem, selector(e.NewItem)); var v = (e.NewItem, selector(e.NewItem));
ringBuffer.AddFirst(v); ringBuffer.AddFirst(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, 0);
} }
else else
{ {
@ -162,7 +162,7 @@ namespace ObservableCollections
{ {
var v = (item, selector(item)); var v = (item, selector(item));
ringBuffer.AddFirst(v); ringBuffer.AddFirst(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, 0);
} }
} }
} }
@ -173,7 +173,7 @@ namespace ObservableCollections
{ {
var v = (e.NewItem, selector(e.NewItem)); var v = (e.NewItem, selector(e.NewItem));
ringBuffer.AddLast(v); ringBuffer.AddLast(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, ringBuffer.Count - 1);
} }
else else
{ {
@ -181,7 +181,7 @@ namespace ObservableCollections
{ {
var v = (item, selector(item)); var v = (item, selector(item));
ringBuffer.AddLast(v); ringBuffer.AddLast(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, ringBuffer.Count - 1);
} }
} }
} }
@ -194,14 +194,14 @@ namespace ObservableCollections
if (e.IsSingleItem) if (e.IsSingleItem)
{ {
var v = ringBuffer.RemoveFirst(); var v = ringBuffer.RemoveFirst();
filter.InvokeOnRemove(v, e); filter.InvokeOnRemove(v, 0);
} }
else else
{ {
for (int i = 0; i < e.OldItems.Length; i++) for (int i = 0; i < e.OldItems.Length; i++)
{ {
var v = ringBuffer.RemoveFirst(); var v = ringBuffer.RemoveFirst();
filter.InvokeOnRemove(v, e); filter.InvokeOnRemove(v, 0);
} }
} }
} }
@ -210,29 +210,32 @@ namespace ObservableCollections
// RemoveLast // RemoveLast
if (e.IsSingleItem) if (e.IsSingleItem)
{ {
var index = ringBuffer.Count - 1;
var v = ringBuffer.RemoveLast(); var v = ringBuffer.RemoveLast();
filter.InvokeOnRemove(v, e); filter.InvokeOnRemove(v, index);
} }
else else
{ {
for (int i = 0; i < e.OldItems.Length; i++) for (int i = 0; i < e.OldItems.Length; i++)
{ {
var index = ringBuffer.Count - 1;
var v = ringBuffer.RemoveLast(); var v = ringBuffer.RemoveLast();
filter.InvokeOnRemove(v, e); filter.InvokeOnRemove(v, index);
} }
} }
} }
break; break;
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
ringBuffer.Clear(); ringBuffer.Clear();
filter.InvokeOnReset(e); filter.InvokeOnReset();
break; break;
case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Replace:
// range is not supported // range is not supported
{ {
var ov = ringBuffer[e.OldStartingIndex];
var v = (e.NewItem, selector(e.NewItem)); var v = (e.NewItem, selector(e.NewItem));
ringBuffer[e.NewStartingIndex] = v; ringBuffer[e.NewStartingIndex] = v;
filter.InvokeOnReplace(v, e); filter.InvokeOnReplace(v, ov, e.NewStartingIndex);
break; break;
} }
case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Move:

View File

@ -63,18 +63,16 @@ namespace ObservableCollections
lock (SyncRoot) lock (SyncRoot)
{ {
this.filter = filter; this.filter = filter;
var i = 0;
foreach (var (value, view) in stack) foreach (var (value, view) in stack)
{ {
if (invokeAddEventForCurrentElements) if (invokeAddEventForCurrentElements)
{ {
filter.InvokeOnAdd(value, view, NotifyCollectionChangedEventArgs<T>.Add(value, i)); filter.InvokeOnAdd(value, view, 0);
} }
else else
{ {
filter.InvokeOnAttach(value, view); filter.InvokeOnAttach(value, view);
} }
i++;
} }
} }
} }
@ -148,7 +146,7 @@ namespace ObservableCollections
{ {
var v = (e.NewItem, selector(e.NewItem)); var v = (e.NewItem, selector(e.NewItem));
stack.Push(v); stack.Push(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, 0);
} }
else else
{ {
@ -156,7 +154,7 @@ namespace ObservableCollections
{ {
var v = (item, selector(item)); var v = (item, selector(item));
stack.Push(v); stack.Push(v);
filter.InvokeOnAdd(v, e); filter.InvokeOnAdd(v, 0);
} }
} }
break; break;
@ -165,7 +163,7 @@ namespace ObservableCollections
if (e.IsSingleItem) if (e.IsSingleItem)
{ {
var v = stack.Pop(); var v = stack.Pop();
filter.InvokeOnRemove(v.Item1, v.Item2, e); filter.InvokeOnRemove(v.Item1, v.Item2, 0);
} }
else else
{ {
@ -173,13 +171,13 @@ namespace ObservableCollections
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
var v = stack.Pop(); var v = stack.Pop();
filter.InvokeOnRemove(v.Item1, v.Item2, e); filter.InvokeOnRemove(v.Item1, v.Item2, 0);
} }
} }
break; break;
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
stack.Clear(); stack.Clear();
filter.InvokeOnReset(e); filter.InvokeOnReset();
break; break;
case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Replace:
case NotifyCollectionChangedAction.Move: case NotifyCollectionChangedAction.Move:

View File

@ -45,9 +45,8 @@ namespace ObservableCollections
{ {
lock (SyncRoot) lock (SyncRoot)
{ {
var index = stack.Count;
stack.Push(item); stack.Push(item);
CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Add(item, index)); CollectionChanged?.Invoke(NotifyCollectionChangedEventArgs<T>.Add(item, 0));
} }
} }

View File

@ -127,29 +127,29 @@ namespace ObservableCollections.Tests
filter3.CalledWhenTrue.Select(x => x.Item1.Value).Should().Equal(-40, -34, -12); filter3.CalledWhenTrue.Select(x => x.Item1.Value).Should().Equal(-40, -34, -12);
dict.Add(99, -100); dict.Add(99, -100);
filter1.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value.Value)).Should().Equal((NotifyCollectionChangedAction.Add, -100)); filter1.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue.Value)).Should().Equal((NotifyCollectionChangedAction.Add, -100));
filter2.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value.Value)).Should().Equal((NotifyCollectionChangedAction.Add, -100)); filter2.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue.Value)).Should().Equal((NotifyCollectionChangedAction.Add, -100));
filter3.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value.Value)).Should().Equal((NotifyCollectionChangedAction.Add, -100)); filter3.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue.Value)).Should().Equal((NotifyCollectionChangedAction.Add, -100));
foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear();
dict[10] = -1090; dict[10] = -1090;
filter1.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value.Value)).Should().Equal((NotifyCollectionChangedAction.Replace, -1090)); filter1.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue.Value, x.OldValue.Value)).Should().Equal((NotifyCollectionChangedAction.Replace, -1090, -12));
filter2.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value.Value)).Should().Equal((NotifyCollectionChangedAction.Replace, -1090)); filter2.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue.Value, x.OldValue.Value)).Should().Equal((NotifyCollectionChangedAction.Replace, -1090, -12));
filter3.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value.Value)).Should().Equal((NotifyCollectionChangedAction.Replace, -1090)); filter3.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue.Value, x.OldValue.Value)).Should().Equal((NotifyCollectionChangedAction.Replace, -1090, -12));
foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear();
dict.Remove(20); dict.Remove(20);
filter1.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value.Value)).Should().Equal((NotifyCollectionChangedAction.Remove, -25)); filter1.CalledOnCollectionChanged.Select(x => (x.Action, x.OldValue.Value)).Should().Equal((NotifyCollectionChangedAction.Remove, -25));
filter2.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value.Value)).Should().Equal((NotifyCollectionChangedAction.Remove, -25)); filter2.CalledOnCollectionChanged.Select(x => (x.Action, x.OldValue.Value)).Should().Equal((NotifyCollectionChangedAction.Remove, -25));
filter3.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value.Value)).Should().Equal((NotifyCollectionChangedAction.Remove, -25)); filter3.CalledOnCollectionChanged.Select(x => (x.Action, x.OldValue.Value)).Should().Equal((NotifyCollectionChangedAction.Remove, -25));
foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear();
dict.Clear(); dict.Clear();
filter1.CalledOnCollectionChanged.Select(x => x.changedAction) filter1.CalledOnCollectionChanged.Select(x => x.Action)
.Should().Equal(NotifyCollectionChangedAction.Reset); .Should().Equal(NotifyCollectionChangedAction.Reset);
filter2.CalledOnCollectionChanged.Select(x => x.changedAction) filter2.CalledOnCollectionChanged.Select(x => x.Action)
.Should().Equal(NotifyCollectionChangedAction.Reset); .Should().Equal(NotifyCollectionChangedAction.Reset);
filter3.CalledOnCollectionChanged.Select(x => x.changedAction) filter3.CalledOnCollectionChanged.Select(x => x.Action)
.Should().Equal(NotifyCollectionChangedAction.Reset); .Should().Equal(NotifyCollectionChangedAction.Reset);
} }
@ -169,16 +169,16 @@ namespace ObservableCollections.Tests
view1.AttachFilter(filter1, true); view1.AttachFilter(filter1, true);
filter1.CalledOnCollectionChanged.Count.Should().Be(5); filter1.CalledOnCollectionChanged.Count.Should().Be(5);
filter1.CalledOnCollectionChanged[0].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter1.CalledOnCollectionChanged[0].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter1.CalledOnCollectionChanged[0].value.Key.Should().Be(10); filter1.CalledOnCollectionChanged[0].NewValue.Key.Should().Be(10);
filter1.CalledOnCollectionChanged[1].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter1.CalledOnCollectionChanged[1].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter1.CalledOnCollectionChanged[1].value.Key.Should().Be(50); filter1.CalledOnCollectionChanged[1].NewValue.Key.Should().Be(50);
filter1.CalledOnCollectionChanged[2].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter1.CalledOnCollectionChanged[2].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter1.CalledOnCollectionChanged[2].value.Key.Should().Be(30); filter1.CalledOnCollectionChanged[2].NewValue.Key.Should().Be(30);
filter1.CalledOnCollectionChanged[3].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter1.CalledOnCollectionChanged[3].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter1.CalledOnCollectionChanged[3].value.Key.Should().Be(20); filter1.CalledOnCollectionChanged[3].NewValue.Key.Should().Be(20);
filter1.CalledOnCollectionChanged[4].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter1.CalledOnCollectionChanged[4].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter1.CalledOnCollectionChanged[4].value.Key.Should().Be(40); filter1.CalledOnCollectionChanged[4].NewValue.Key.Should().Be(40);
filter1.CalledWhenTrue.Count.Should().Be(3); filter1.CalledWhenTrue.Count.Should().Be(3);
filter1.CalledWhenFalse.Count.Should().Be(2); filter1.CalledWhenFalse.Count.Should().Be(2);

View File

@ -70,12 +70,12 @@ namespace ObservableCollections.Tests
set.Add(33); set.Add(33);
set.AddRange(new[] { 98 }); set.AddRange(new[] { 98 });
filter.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Add, 33), (NotifyCollectionChangedAction.Add, 98)); filter.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue)).Should().Equal((NotifyCollectionChangedAction.Add, 33), (NotifyCollectionChangedAction.Add, 98));
filter.Clear(); filter.Clear();
set.Remove(10); set.Remove(10);
set.RemoveRange(new[] { 50, 30 }); set.RemoveRange(new[] { 50, 30 });
filter.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Remove, 10), (NotifyCollectionChangedAction.Remove, 50), (NotifyCollectionChangedAction.Remove, 30)); filter.CalledOnCollectionChanged.Select(x => (x.Action, x.OldValue)).Should().Equal((NotifyCollectionChangedAction.Remove, 10), (NotifyCollectionChangedAction.Remove, 50), (NotifyCollectionChangedAction.Remove, 30));
} }
[Fact] [Fact]
@ -93,16 +93,16 @@ namespace ObservableCollections.Tests
view.AttachFilter(filter, true); view.AttachFilter(filter, true);
filter.CalledOnCollectionChanged.Count.Should().Be(5); filter.CalledOnCollectionChanged.Count.Should().Be(5);
filter.CalledOnCollectionChanged[0].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[0].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[0].value.Should().Be(10); filter.CalledOnCollectionChanged[0].NewValue.Should().Be(10);
filter.CalledOnCollectionChanged[1].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[1].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[1].value.Should().Be(50); filter.CalledOnCollectionChanged[1].NewValue.Should().Be(50);
filter.CalledOnCollectionChanged[2].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[2].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[2].value.Should().Be(30); filter.CalledOnCollectionChanged[2].NewValue.Should().Be(30);
filter.CalledOnCollectionChanged[3].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[3].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[3].value.Should().Be(20); filter.CalledOnCollectionChanged[3].NewValue.Should().Be(20);
filter.CalledOnCollectionChanged[4].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[4].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[4].value.Should().Be(40); filter.CalledOnCollectionChanged[4].NewValue.Should().Be(40);
filter.CalledWhenTrue.Count.Should().Be(1); filter.CalledWhenTrue.Count.Should().Be(1);
filter.CalledWhenFalse.Count.Should().Be(4); filter.CalledWhenFalse.Count.Should().Be(4);

View File

@ -179,45 +179,45 @@ namespace ObservableCollections.Tests
filter2.CalledWhenFalse.Select(x => x.Item1).Should().Equal(101); filter2.CalledWhenFalse.Select(x => x.Item1).Should().Equal(101);
filter3.CalledWhenFalse.Select(x => x.Item1).Should().Equal(101); filter3.CalledWhenFalse.Select(x => x.Item1).Should().Equal(101);
filter1.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Add, 100), (NotifyCollectionChangedAction.Add, 101)); filter1.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex)).Should().Equal((NotifyCollectionChangedAction.Add, 100, 7), (NotifyCollectionChangedAction.Add, 101, 8));
filter2.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Add, 100), (NotifyCollectionChangedAction.Add, 101)); filter2.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex)).Should().Equal((NotifyCollectionChangedAction.Add, 100, 7), (NotifyCollectionChangedAction.Add, 101, 8));
filter3.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Add, 100), (NotifyCollectionChangedAction.Add, 101)); filter3.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex)).Should().Equal((NotifyCollectionChangedAction.Add, 100, 7), (NotifyCollectionChangedAction.Add, 101, 8));
foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear();
list.Insert(0, 1000); list.Insert(0, 1000);
list.InsertRange(0, new[] { 999 }); list.InsertRange(0, new[] { 999 });
filter1.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Add, 1000), (NotifyCollectionChangedAction.Add, 999)); filter1.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex)).Should().Equal((NotifyCollectionChangedAction.Add, 1000, 0), (NotifyCollectionChangedAction.Add, 999, 0));
filter2.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Add, 1000), (NotifyCollectionChangedAction.Add, 999)); filter2.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex)).Should().Equal((NotifyCollectionChangedAction.Add, 1000, 9), (NotifyCollectionChangedAction.Add, 999, 9)); // sorted index
filter3.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Add, 1000), (NotifyCollectionChangedAction.Add, 999)); filter3.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex)).Should().Equal((NotifyCollectionChangedAction.Add, 1000, 9), (NotifyCollectionChangedAction.Add, 999, 9)); // sorted index
foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear();
list.RemoveAt(0); list.RemoveAt(0);
list.RemoveRange(0, 1); list.RemoveRange(0, 1);
filter1.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Remove, 999), (NotifyCollectionChangedAction.Remove, 1000)); filter1.CalledOnCollectionChanged.Select(x => (x.Action, x.OldValue, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Remove, 999, 0), (NotifyCollectionChangedAction.Remove, 1000, 0));
filter2.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Remove, 999), (NotifyCollectionChangedAction.Remove, 1000)); filter2.CalledOnCollectionChanged.Select(x => (x.Action, x.OldValue, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Remove, 999, 9), (NotifyCollectionChangedAction.Remove, 1000, 9));
filter3.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Remove, 999), (NotifyCollectionChangedAction.Remove, 1000)); filter3.CalledOnCollectionChanged.Select(x => (x.Action, x.OldValue, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Remove, 999, 9), (NotifyCollectionChangedAction.Remove, 1000, 9));
foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear();
list[0] = 9999; list[0] = 9999;
filter1.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Replace, 9999)); filter1.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Replace, 9999, 0, 0));
filter2.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Replace, 9999)); filter2.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Replace, 9999, 8, 0));
filter3.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Replace, 9999)); filter3.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Replace, 9999, 8, 0));
foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear();
list.Move(3, 0); list.Move(3, 0);
filter1.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Move, 44)); filter1.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Move, 44, 0, 3));
filter2.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Move, 44)); filter2.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Move, 44, 2, 2));
filter3.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Move, 44)); filter3.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Move, 44, 2, 2));
foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear(); foreach (var item in new[] { filter1, filter2, filter3 }) item.CalledOnCollectionChanged.Clear();
list.Clear(); list.Clear();
filter1.CalledOnCollectionChanged.Select(x => x.changedAction).Should().Equal(NotifyCollectionChangedAction.Reset); filter1.CalledOnCollectionChanged.Select(x => x.Action).Should().Equal(NotifyCollectionChangedAction.Reset);
filter2.CalledOnCollectionChanged.Select(x => x.changedAction).Should().Equal(NotifyCollectionChangedAction.Reset); filter2.CalledOnCollectionChanged.Select(x => x.Action).Should().Equal(NotifyCollectionChangedAction.Reset);
filter3.CalledOnCollectionChanged.Select(x => x.changedAction).Should().Equal(NotifyCollectionChangedAction.Reset); filter3.CalledOnCollectionChanged.Select(x => x.Action).Should().Equal(NotifyCollectionChangedAction.Reset);
} }
[Fact] [Fact]
@ -230,14 +230,14 @@ namespace ObservableCollections.Tests
var filter1 = new TestFilter<int>((x, v) => x % 2 == 0); var filter1 = new TestFilter<int>((x, v) => x % 2 == 0);
view1.AttachFilter(filter1, true); view1.AttachFilter(filter1, true);
filter1.CalledOnCollectionChanged[0].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter1.CalledOnCollectionChanged[0].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter1.CalledOnCollectionChanged[0].value.Should().Be(10); filter1.CalledOnCollectionChanged[0].NewValue.Should().Be(10);
filter1.CalledOnCollectionChanged[1].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter1.CalledOnCollectionChanged[1].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter1.CalledOnCollectionChanged[1].value.Should().Be(21); filter1.CalledOnCollectionChanged[1].NewValue.Should().Be(21);
filter1.CalledOnCollectionChanged[2].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter1.CalledOnCollectionChanged[2].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter1.CalledOnCollectionChanged[2].value.Should().Be(30); filter1.CalledOnCollectionChanged[2].NewValue.Should().Be(30);
filter1.CalledOnCollectionChanged[3].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter1.CalledOnCollectionChanged[3].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter1.CalledOnCollectionChanged[3].value.Should().Be(44); filter1.CalledOnCollectionChanged[3].NewValue.Should().Be(44);
filter1.CalledWhenTrue.Count.Should().Be(3); filter1.CalledWhenTrue.Count.Should().Be(3);
filter1.CalledWhenFalse.Count.Should().Be(1); filter1.CalledWhenFalse.Count.Should().Be(1);

View File

@ -74,12 +74,12 @@ namespace ObservableCollections.Tests
queue.Enqueue(33); queue.Enqueue(33);
queue.EnqueueRange(new[] { 98 }); queue.EnqueueRange(new[] { 98 });
filter.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Add, 33), (NotifyCollectionChangedAction.Add, 98)); filter.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex)).Should().Equal((NotifyCollectionChangedAction.Add, 33, 5), (NotifyCollectionChangedAction.Add, 98, 6));
filter.Clear(); filter.Clear();
queue.Dequeue(); queue.Dequeue();
queue.DequeueRange(2); queue.DequeueRange(2);
filter.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Remove, 10), (NotifyCollectionChangedAction.Remove, 50), (NotifyCollectionChangedAction.Remove, 30)); filter.CalledOnCollectionChanged.Select(x => (x.Action, x.OldValue, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Remove, 10, 0), (NotifyCollectionChangedAction.Remove, 50, 0), (NotifyCollectionChangedAction.Remove, 30, 0));
} }
[Fact] [Fact]
@ -98,16 +98,21 @@ namespace ObservableCollections.Tests
view.AttachFilter(filter, true); view.AttachFilter(filter, true);
filter.CalledOnCollectionChanged.Count.Should().Be(5); filter.CalledOnCollectionChanged.Count.Should().Be(5);
filter.CalledOnCollectionChanged[0].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[0].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[0].value.Should().Be(10); filter.CalledOnCollectionChanged[0].NewValue.Should().Be(10);
filter.CalledOnCollectionChanged[1].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[0].NewViewIndex.Should().Be(0);
filter.CalledOnCollectionChanged[1].value.Should().Be(50); filter.CalledOnCollectionChanged[1].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[2].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[1].NewValue.Should().Be(50);
filter.CalledOnCollectionChanged[2].value.Should().Be(30); filter.CalledOnCollectionChanged[1].NewViewIndex.Should().Be(1);
filter.CalledOnCollectionChanged[3].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[2].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[3].value.Should().Be(20); filter.CalledOnCollectionChanged[2].NewValue.Should().Be(30);
filter.CalledOnCollectionChanged[4].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[2].NewViewIndex.Should().Be(2);
filter.CalledOnCollectionChanged[4].value.Should().Be(40); filter.CalledOnCollectionChanged[3].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[3].NewValue.Should().Be(20);
filter.CalledOnCollectionChanged[3].NewViewIndex.Should().Be(3);
filter.CalledOnCollectionChanged[4].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[4].NewValue.Should().Be(40);
filter.CalledOnCollectionChanged[4].NewViewIndex.Should().Be(4);
filter.CalledWhenTrue.Count.Should().Be(1); filter.CalledWhenTrue.Count.Should().Be(1);
filter.CalledWhenFalse.Count.Should().Be(4); filter.CalledWhenFalse.Count.Should().Be(4);

View File

@ -74,12 +74,12 @@ namespace ObservableCollections.Tests
stack.Push(33); stack.Push(33);
stack.PushRange(new[] { 98 }); stack.PushRange(new[] { 98 });
filter.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Add, 33), (NotifyCollectionChangedAction.Add, 98)); filter.CalledOnCollectionChanged.Select(x => (x.Action, x.NewValue, x.NewViewIndex)).Should().Equal((NotifyCollectionChangedAction.Add, 33, 0), (NotifyCollectionChangedAction.Add, 98, 0));
filter.Clear(); filter.Clear();
stack.Pop(); stack.Pop();
stack.PopRange(2); stack.PopRange(2);
filter.CalledOnCollectionChanged.Select(x => (x.changedAction, x.value)).Should().Equal((NotifyCollectionChangedAction.Remove, 98), (NotifyCollectionChangedAction.Remove, 33), (NotifyCollectionChangedAction.Remove, 40)); filter.CalledOnCollectionChanged.Select(x => (x.Action, x.OldValue, x.OldViewIndex)).Should().Equal((NotifyCollectionChangedAction.Remove, 98, 0), (NotifyCollectionChangedAction.Remove, 33, 0), (NotifyCollectionChangedAction.Remove, 40, 0));
} }
[Fact] [Fact]
@ -97,16 +97,21 @@ namespace ObservableCollections.Tests
view.AttachFilter(filter, true); view.AttachFilter(filter, true);
filter.CalledOnCollectionChanged.Count.Should().Be(5); filter.CalledOnCollectionChanged.Count.Should().Be(5);
filter.CalledOnCollectionChanged[4].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[4].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[4].value.Should().Be(10); filter.CalledOnCollectionChanged[4].NewValue.Should().Be(10);
filter.CalledOnCollectionChanged[3].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[4].NewViewIndex.Should().Be(0);
filter.CalledOnCollectionChanged[3].value.Should().Be(50); filter.CalledOnCollectionChanged[3].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[2].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[3].NewValue.Should().Be(50);
filter.CalledOnCollectionChanged[2].value.Should().Be(30); filter.CalledOnCollectionChanged[3].NewViewIndex.Should().Be(0);
filter.CalledOnCollectionChanged[1].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[2].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[1].value.Should().Be(20); filter.CalledOnCollectionChanged[2].NewValue.Should().Be(30);
filter.CalledOnCollectionChanged[0].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[2].NewViewIndex.Should().Be(0);
filter.CalledOnCollectionChanged[0].value.Should().Be(40); filter.CalledOnCollectionChanged[1].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[1].NewValue.Should().Be(20);
filter.CalledOnCollectionChanged[1].NewViewIndex.Should().Be(0);
filter.CalledOnCollectionChanged[0].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[0].NewValue.Should().Be(40);
filter.CalledOnCollectionChanged[0].NewViewIndex.Should().Be(0);
filter.CalledWhenTrue.Count.Should().Be(1); filter.CalledWhenTrue.Count.Should().Be(1);
filter.CalledWhenFalse.Count.Should().Be(4); filter.CalledWhenFalse.Count.Should().Be(4);

View File

@ -50,19 +50,21 @@ public class SortedViewTest
sortedView.AttachFilter(filter); sortedView.AttachFilter(filter);
list.Add(20); list.Add(20);
filter.CalledOnCollectionChanged[0].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[0].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[0].value.Should().Be(20); filter.CalledOnCollectionChanged[0].NewValue.Should().Be(20);
filter.CalledOnCollectionChanged[0].index.Should().Be(1); filter.CalledOnCollectionChanged[0].NewView.Should().Be(new ViewContainer<int>(20));
filter.CalledOnCollectionChanged[0].NewViewIndex.Should().Be(1);
list.Remove(20); list.Remove(20);
filter.CalledOnCollectionChanged[1].changedAction.Should().Be(NotifyCollectionChangedAction.Remove); filter.CalledOnCollectionChanged[1].Action.Should().Be(NotifyCollectionChangedAction.Remove);
filter.CalledOnCollectionChanged[1].value.Should().Be(20); filter.CalledOnCollectionChanged[1].OldValue.Should().Be(20);
filter.CalledOnCollectionChanged[1].oldIndex.Should().Be(1); filter.CalledOnCollectionChanged[1].OldView.Should().Be(new ViewContainer<int>(20));
filter.CalledOnCollectionChanged[1].OldViewIndex.Should().Be(1);
list[1] = 999; // from 10(at 0 in original) to 999 list[1] = 999; // from 10(at 0 in original) to 999
filter.CalledOnCollectionChanged[2].changedAction.Should().Be(NotifyCollectionChangedAction.Replace); filter.CalledOnCollectionChanged[2].Action.Should().Be(NotifyCollectionChangedAction.Replace);
filter.CalledOnCollectionChanged[2].value.Should().Be(999); filter.CalledOnCollectionChanged[2].NewValue.Should().Be(999);
filter.CalledOnCollectionChanged[2].index.Should().Be(1); filter.CalledOnCollectionChanged[2].OldValue.Should().Be(10);
filter.CalledOnCollectionChanged[2].oldIndex.Should().Be(0); filter.CalledOnCollectionChanged[2].NewViewIndex.Should().Be(1);
} }
} }

View File

@ -50,19 +50,24 @@ public class SortedViewViewComparerTest
sortedView.AttachFilter(filter); sortedView.AttachFilter(filter);
list.Add(20); list.Add(20);
filter.CalledOnCollectionChanged[0].changedAction.Should().Be(NotifyCollectionChangedAction.Add); filter.CalledOnCollectionChanged[0].Action.Should().Be(NotifyCollectionChangedAction.Add);
filter.CalledOnCollectionChanged[0].value.Should().Be(20); filter.CalledOnCollectionChanged[0].NewValue.Should().Be(20);
filter.CalledOnCollectionChanged[0].index.Should().Be(1); filter.CalledOnCollectionChanged[0].NewView.Should().Be(new ViewContainer<int>(20));
filter.CalledOnCollectionChanged[0].NewViewIndex.Should().Be(1);
list.Remove(20); list.Remove(20);
filter.CalledOnCollectionChanged[1].changedAction.Should().Be(NotifyCollectionChangedAction.Remove); filter.CalledOnCollectionChanged[1].Action.Should().Be(NotifyCollectionChangedAction.Remove);
filter.CalledOnCollectionChanged[1].value.Should().Be(20); filter.CalledOnCollectionChanged[1].OldValue.Should().Be(20);
filter.CalledOnCollectionChanged[1].oldIndex.Should().Be(1); filter.CalledOnCollectionChanged[1].OldView.Should().Be(new ViewContainer<int>(20));
filter.CalledOnCollectionChanged[1].OldViewIndex.Should().Be(1);
list[1] = 999; // from 10(at 0 in original) to 999 list[1] = 999; // from 10(at 0 in original) to 999
filter.CalledOnCollectionChanged[2].changedAction.Should().Be(NotifyCollectionChangedAction.Replace); filter.CalledOnCollectionChanged[2].Action.Should().Be(NotifyCollectionChangedAction.Replace);
filter.CalledOnCollectionChanged[2].value.Should().Be(999); filter.CalledOnCollectionChanged[2].NewValue.Should().Be(999);
filter.CalledOnCollectionChanged[2].index.Should().Be(1); filter.CalledOnCollectionChanged[2].OldValue.Should().Be(10);
filter.CalledOnCollectionChanged[2].oldIndex.Should().Be(0); filter.CalledOnCollectionChanged[2].NewView.Should().Be(new ViewContainer<int>(999));
filter.CalledOnCollectionChanged[2].OldView.Should().Be(new ViewContainer<int>(10));
filter.CalledOnCollectionChanged[2].NewViewIndex.Should().Be(1);
filter.CalledOnCollectionChanged[2].OldViewIndex.Should().Be(0);
} }
} }

View File

@ -36,7 +36,7 @@ namespace ObservableCollections.Tests
readonly Func<T, ViewContainer<T>, bool> filter; readonly Func<T, ViewContainer<T>, bool> filter;
public List<(T, ViewContainer<T>)> CalledWhenTrue = new(); public List<(T, ViewContainer<T>)> CalledWhenTrue = new();
public List<(T, ViewContainer<T>)> CalledWhenFalse = new(); public List<(T, ViewContainer<T>)> CalledWhenFalse = new();
public List<(NotifyCollectionChangedAction changedAction, T value, ViewContainer<T> view, int index, int oldIndex)> CalledOnCollectionChanged = new(); public List<SynchronizedViewChangedEventArgs<T, ViewContainer<T>>> CalledOnCollectionChanged = new();
public TestFilter(Func<T, ViewContainer<T>, bool> filter) public TestFilter(Func<T, ViewContainer<T>, bool> filter)
{ {
@ -55,9 +55,9 @@ namespace ObservableCollections.Tests
return this.filter.Invoke(value, view); return this.filter.Invoke(value, view);
} }
public void OnCollectionChanged(NotifyCollectionChangedAction changedAction, T value, ViewContainer<T> view, in NotifyCollectionChangedEventArgs<T> eventArgs) public void OnCollectionChanged(in SynchronizedViewChangedEventArgs<T, ViewContainer<T>> args)
{ {
CalledOnCollectionChanged.Add((changedAction, value, view, eventArgs.NewStartingIndex, eventArgs.OldStartingIndex)); CalledOnCollectionChanged.Add(args);
} }
public void WhenTrue(T value, ViewContainer<T> view) public void WhenTrue(T value, ViewContainer<T> view)
@ -76,7 +76,7 @@ namespace ObservableCollections.Tests
readonly Func<KeyValuePair<T, T>, ViewContainer<T>, bool> filter; readonly Func<KeyValuePair<T, T>, ViewContainer<T>, bool> filter;
public List<(KeyValuePair<T, T>, ViewContainer<T>)> CalledWhenTrue = new(); public List<(KeyValuePair<T, T>, ViewContainer<T>)> CalledWhenTrue = new();
public List<(KeyValuePair<T, T>, ViewContainer<T>)> CalledWhenFalse = new(); public List<(KeyValuePair<T, T>, ViewContainer<T>)> CalledWhenFalse = new();
public List<(NotifyCollectionChangedAction changedAction, KeyValuePair<T, T> value, ViewContainer<T> view)> CalledOnCollectionChanged = new(); public List<SynchronizedViewChangedEventArgs<KeyValuePair<T, T>, ViewContainer<T>>> CalledOnCollectionChanged = new();
public TestFilter2(Func<KeyValuePair<T, T>, ViewContainer<T>, bool> filter) public TestFilter2(Func<KeyValuePair<T, T>, ViewContainer<T>, bool> filter)
{ {
@ -95,9 +95,9 @@ namespace ObservableCollections.Tests
return this.filter.Invoke(value, view); return this.filter.Invoke(value, view);
} }
public void OnCollectionChanged(NotifyCollectionChangedAction changedAction, KeyValuePair<T, T> value, ViewContainer<T> view, in NotifyCollectionChangedEventArgs<KeyValuePair<T, T>> eventArgs) public void OnCollectionChanged(in SynchronizedViewChangedEventArgs<KeyValuePair<T, T>, ViewContainer<T>> args)
{ {
CalledOnCollectionChanged.Add((changedAction, value, view)); CalledOnCollectionChanged.Add(args);
} }
public void WhenTrue(KeyValuePair<T, T> value, ViewContainer<T> view) public void WhenTrue(KeyValuePair<T, T> value, ViewContainer<T> view)