Skip to content

Commit

Permalink
WAF SynchronizingList add support for IEnumerable and isReadOnly flag
Browse files Browse the repository at this point in the history
  • Loading branch information
jbe2277 committed Sep 26, 2023
1 parent 0b49d4d commit 6914fa0
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,35 @@ void OuterHandler(object? sender, NotifyCollectionChangedEventArgs e)
}
}

[TestMethod]
public void ReadOnlyListErrorTest()
{
var originalList = new ObservableList<MyModel>()
{
new MyModel(),
new MyModel(),
new MyModel()
};

var readOnlyList = (IReadOnlyList<MyModel>)originalList;
var synchronizingList = new SynchronizingList<MyDataModel, MyModel>(readOnlyList, m => new MyDataModel(m));
CoreTest();

synchronizingList = new SynchronizingList<MyDataModel, MyModel>(originalList, m => new MyDataModel(m), isReadOnly: true);
CoreTest();

void CoreTest()
{
AssertHelper.SequenceEqual(originalList, synchronizingList.Select(dm => dm.Model));
AssertHelper.ExpectedException<NotSupportedException>(() => synchronizingList.RemoveAt(1));
AssertHelper.ExpectedException<NotSupportedException>(() => synchronizingList.Move(0, 1));
AssertHelper.ExpectedException<NotSupportedException>(() => synchronizingList.Clear());
var newModel = new MyModel();
originalList.Add(newModel);
Assert.AreSame(newModel, synchronizingList.Last().Model);
}
}

[TestMethod]
public void PropertyChangedTest()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,37 @@ public class SynchronizingList<T, TOriginal> : ObservableList<T>
private readonly List<(TOriginal original, T newItem)> mapping = new();
private readonly IEqualityComparer<T> itemComparer = EqualityComparer<T>.Default;
private readonly IEqualityComparer<TOriginal> originalItemComparer = EqualityComparer<TOriginal>.Default;
private readonly ObservableCollection<TOriginal> originalList;
private readonly IEnumerable<TOriginal> originalCollection;
private readonly ObservableCollection<TOriginal>? originalList;
private readonly Func<TOriginal, T> factory;
private readonly bool isReadOnly;
private bool innerChange;

/// <summary>Initializes a new instance of the <see cref="SynchronizingList{T, TOriginal}"/> class.</summary>
/// <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>
/// <param name="factory">The factory which is used to create new elements in this collection.</param>
/// <exception cref="ArgumentNullException">The argument originalCollection must not be null.</exception>
/// <exception cref="ArgumentNullException">The argument factory must not be null.</exception>
public SynchronizingList(ObservableCollection<TOriginal> originalList, Func<TOriginal, T> factory)
/// <param name="isReadOnly">Set true to define a read-only synchronizing list, otherwise set false.</param>
/// <exception cref="ArgumentNullException">The arguments originalCollection and factory must not be null.</exception>
public SynchronizingList(ObservableCollection<TOriginal> originalList, Func<TOriginal, T> factory, bool isReadOnly = false) : this(originalList, originalList, factory, isReadOnly) { }

/// <summary>Initializes a new instance of the <see cref="SynchronizingList{T, TOriginal}"/> class with one-way synchronization support. The instance is read-only.</summary>
/// <param name="originalCollection">The original collection.</param>
/// <param name="factory">The factory which is used to create new elements in this collection.</param>
/// <exception cref="ArgumentNullException">The arguments originalCollection and factory must not be null.</exception>
public SynchronizingList(IEnumerable<TOriginal> originalCollection, Func<TOriginal, T> factory) : this(null, originalCollection, factory) { }

private SynchronizingList(ObservableCollection<TOriginal>? originalList, IEnumerable<TOriginal> originalCollection, Func<TOriginal, T> factory, bool isReadOnly = false)
{
this.originalList = originalList ?? throw new ArgumentNullException(nameof(originalList));
this.originalList = originalList;
this.originalCollection = originalCollection ?? throw new ArgumentNullException(nameof(originalCollection));
this.factory = factory ?? throw new ArgumentNullException(nameof(factory));
this.isReadOnly = originalList is null || isReadOnly;

WeakEvent.CollectionChanged.Add(originalList, OriginalCollectionChanged);
INotifyCollectionChanged? observableCollection = originalList ?? originalCollection as INotifyCollectionChanged;
if (observableCollection is not null) WeakEvent.CollectionChanged.Add(observableCollection, OriginalCollectionChanged);

innerChange = true;
foreach (TOriginal x in originalList) Add(CreateItem(x));
foreach (TOriginal x in originalCollection) Add(CreateItem(x));
innerChange = false;
}

Expand Down Expand Up @@ -94,7 +107,7 @@ private void OriginalCollectionChanged(object? sender, NotifyCollectionChangedEv
else // Reset
{
ClearCore();
foreach (TOriginal x in originalList) Add(CreateItem(x));
foreach (TOriginal x in originalCollection) Add(CreateItem(x));
}
}
finally
Expand All @@ -121,21 +134,27 @@ protected override void SetItem(int index, T item)
protected override void RemoveItem(int index)
{
if (innerChange) base.RemoveItem(index);
else originalList.RemoveAt(index);
else ModifyOriginalList().RemoveAt(index);
}

/// <inheritdoc />
protected override void ClearItems()
{
if (innerChange) base.ClearItems();
else originalList.Clear();
else ModifyOriginalList().Clear();
}

/// <inheritdoc />
protected override void MoveItem(int oldIndex, int newIndex)
{
if (innerChange) base.MoveItem(oldIndex, newIndex);
else originalList.Move(oldIndex, newIndex);
else ModifyOriginalList().Move(oldIndex, newIndex);
}

private ObservableCollection<TOriginal> ModifyOriginalList()
{
if (isReadOnly) throw new NotSupportedException("IsReadOnly is true. Modifications are not allowed.");
return originalList!;
}

private T CreateItem([AllowNull] TOriginal oldItem)
Expand Down

0 comments on commit 6914fa0

Please sign in to comment.