Skip to content

Commit

Permalink
WAF SynchronizingList improve two-way synchronization by not re-creat…
Browse files Browse the repository at this point in the history
…ing a model upon Insert or SetItem
  • Loading branch information
jbe2277 committed Oct 2, 2023
1 parent eb317a2 commit 2ce9311
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ public void SynchronizeWithGetOriginalItemTest()
};
AssertCollectionChangeEventsCalled(handler, () => originalList.Add(new MyModel()));
originalList.Remove(originalList.Last());
AssertCollectionChangeEventsCalled(handler, () => synchronizingList.Add(new MyDataModel(new MyModel())));
var dataModelToAdd = new MyDataModel(new MyModel());
AssertCollectionChangeEventsCalled(handler, () => synchronizingList.Add(dataModelToAdd));
Assert.AreSame(dataModelToAdd, synchronizingList.Last());

// Check insert at index 0 operation with collection changed event.
handler = (sender, e) =>
Expand All @@ -132,7 +134,21 @@ public void SynchronizeWithGetOriginalItemTest()
};
AssertCollectionChangeEventsCalled(handler, () => originalList.Insert(0, new MyModel()));
originalList.RemoveAt(0);
AssertCollectionChangeEventsCalled(handler, () => synchronizingList.Insert(0, new MyDataModel(new MyModel())));
var dataModelToInsert = new MyDataModel(new MyModel());
AssertCollectionChangeEventsCalled(handler, () => synchronizingList.Insert(0, dataModelToInsert));
Assert.AreSame(dataModelToInsert, synchronizingList[0]);

// Check replace operation with collection changed event.
handler = (sender, e) =>
{
Assert.AreEqual(NotifyCollectionChangedAction.Replace, e.Action);
Assert.AreEqual(0, e.NewStartingIndex);
Assert.AreEqual(originalList[0], e.NewItems!.Cast<MyDataModel>().Single().Model);
};
AssertCollectionChangeEventsCalled(handler, () => originalList[0] = new MyModel());
var dataModelToReplace = new MyDataModel(new MyModel());
AssertCollectionChangeEventsCalled(handler, () => synchronizingList[0] = dataModelToReplace);
Assert.AreSame(dataModelToReplace, synchronizingList[0]);

// Compare the collections
AssertHelper.SequenceEqual(originalList, synchronizingList.Select(dm => dm.Model));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class SynchronizingList<T, TOriginal> : ObservableList<T>
private readonly Func<T, TOriginal>? getOriginalItem;
private readonly bool isReadOnly;
private bool innerChange;
private bool outerChange;

/// <summary>Initializes a new instance of the <see cref="SynchronizingList{T, TOriginal}"/> class with two-way synchronization support.</summary>
/// <param name="originalList">The original list.</param>
Expand Down Expand Up @@ -61,6 +62,7 @@ private SynchronizingList(ObservableCollection<TOriginal>? originalList, IEnumer
private void OriginalCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e == null) throw new ArgumentNullException(nameof(e));
if (outerChange) return;
innerChange = true;
try
{
Expand Down Expand Up @@ -116,24 +118,32 @@ private void OriginalCollectionChanged(object? sender, NotifyCollectionChangedEv
foreach (TOriginal x in originalCollection) Add(CreateItem(x));
}
}
finally
{
innerChange = false;
}
finally { innerChange = false; }
}

/// <inheritdoc />
protected override void InsertItem(int index, T item)
{
if (innerChange) base.InsertItem(index, item);
else ModifyOriginalList().Insert(index, GetOriginalItem(item));
if (!innerChange)
{
outerChange = true;
try { ModifyOriginalList().Insert(index, GetOriginalItem(item)); }
finally { outerChange = false; }
}
base.InsertItem(index, item);

}

/// <inheritdoc />
protected override void SetItem(int index, T item)
{
if (innerChange) base.SetItem(index, item);
else ModifyOriginalList()[index] = GetOriginalItem(item);
if (!innerChange)
{
outerChange = true;
try { ModifyOriginalList()[index] = GetOriginalItem(item); }
finally { outerChange = false; }
}
base.SetItem(index, item);
}

/// <inheritdoc />
Expand Down

0 comments on commit 2ce9311

Please sign in to comment.