Skip to content

Commit

Permalink
WAF ObservableListViewBase: restore original DeferCollectionChangedNo…
Browse files Browse the repository at this point in the history
…tifications behavior
  • Loading branch information
jbe2277 committed Sep 25, 2023
1 parent edfff41 commit 0a10e0a
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ public void RelayEventsWithDefer()
using (var deferral2 = observableListView.DeferCollectionChangedNotifications())
{
originalList.Add("first");
Assert.AreEqual(1, collectionChangingList.Count);
Assert.AreEqual(0, collectionChangedList.Count);
Assert.AreEqual(1, countChangedCount);
Assert.AreEqual(1, indexerChangedCount);
originalList.Add("second");
Expand All @@ -265,16 +267,15 @@ public void RelayEventsWithDefer()
originalList.Add("third");

countChangedCount = indexerChangedCount = 0;
Assert.AreEqual(5, collectionChangingList.Count);
Assert.AreEqual(1, collectionChangingList.Count);
Assert.AreEqual(0, collectionChangedList.Count);
}
Assert.AreEqual(5, collectionChangingList.Count);
Assert.AreEqual(1, collectionChangingList.Count);
Assert.AreEqual(0, collectionChangedList.Count);
deferral1.Dispose(); // call Dispose twice to see if this works too
}
AssertHelper.SequenceEqual(new[] { NotifyCollectionChangedAction.Add, NotifyCollectionChangedAction.Add, NotifyCollectionChangedAction.Move,
NotifyCollectionChangedAction.Remove, NotifyCollectionChangedAction.Add }, collectionChangedList.Select(x => x.Action));
AssertHelper.SequenceEqual(collectionChangedList, collectionChangingList);
Assert.AreEqual(NotifyCollectionChangedAction.Reset, collectionChangingList.Single().Action);
Assert.AreEqual(NotifyCollectionChangedAction.Reset, collectionChangedList.Single().Action);
Assert.AreEqual(0, countChangedCount);
Assert.AreEqual(0, indexerChangedCount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ namespace System.Waf.Foundation
/// <typeparam name="T">The type of elements in the collection.</typeparam>
public abstract class ObservableListViewBase<T> : ReadOnlyCollection<T>, IReadOnlyObservableList<T>, INotifyCollectionChanging
{
private readonly object deferredChangesLock = new();
private List<NotifyCollectionChangedEventArgs>? deferredChanges;
private int deferredChanges;
private int deferCount;

/// <summary>Initializes a new instance of the ObservableListViewBase class.</summary>
/// <param name="originalList">Initialize the list view with the items from this list.</param>
protected ObservableListViewBase(IEnumerable<T>? originalList) : base(new List<T>())
Expand Down Expand Up @@ -42,39 +41,27 @@ public IDisposable DeferCollectionChangedNotifications()
Interlocked.Increment(ref deferCount);
return new DisposedNotifier(() =>
{
if (Interlocked.Decrement(ref deferCount) == 0)
if (Interlocked.Decrement(ref deferCount) == 0 && Interlocked.Exchange(ref deferredChanges, 0) > 0)
{
List<NotifyCollectionChangedEventArgs>? replayChanges;
lock (deferredChangesLock)
{
replayChanges = deferredChanges;
deferredChanges = null;
}
if (replayChanges is not null)
{
foreach (var x in replayChanges) OnCollectionChanged(x);
}
OnCollectionChanged(EventArgsCache.ResetCollectionChanged);
}
});
}

/// <summary>Raises the CollectionChanged event with the provided arguments.</summary>
/// <param name="e">Arguments of the event being raised.</param>
protected virtual void OnCollectionChanging(NotifyCollectionChangedEventArgs e) => CollectionChanging?.Invoke(this, e);
protected virtual void OnCollectionChanging(NotifyCollectionChangedEventArgs e)
{
if (deferCount <= 0) CollectionChanging?.Invoke(this, e);
else if (deferredChanges == 0) CollectionChanging?.Invoke(this, EventArgsCache.ResetCollectionChanged);
}

/// <summary>Raises the CollectionChanged event with the provided arguments.</summary>
/// <param name="e">Arguments of the event being raised.</param>
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (deferCount > 0)
{
lock (deferredChangesLock)
{
deferredChanges ??= new();
deferredChanges.Add(e);
}
}
else { CollectionChanged?.Invoke(this, e); }
if (deferCount <= 0) CollectionChanged?.Invoke(this, e);
else Interlocked.Increment(ref deferredChanges);
}

/// <summary>Raises the PropertyChanged event with the provided arguments.</summary>
Expand Down

0 comments on commit 0a10e0a

Please sign in to comment.