Skip to content

Commit

Permalink
WAF: ObservableList uses weak event to listen for the PropertyChanged…
Browse files Browse the repository at this point in the history
… event of the items
jbe2277 committed Feb 9, 2024
1 parent e35ac68 commit eb09d13
Showing 3 changed files with 46 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -155,6 +155,26 @@ internal static void CollectionItemChangedTestCore(ObservableCollection<Collecti
void CollectionItemChangedHandler(object? item, PropertyChangedEventArgs e) => collectionItemChangedList.Add((item, e.PropertyName));
}

[TestMethod]
public void CollectionItemChangedWeakTest()
{
CollectionItemChangedWeakCoreTest(() => new ObservableList<CollectionEventsTestModel>(new[] { new CollectionEventsTestModel() }));
}

internal static void CollectionItemChangedWeakCoreTest(Func<IList<CollectionEventsTestModel>> factory)
{
var (weakList, item1) = Core();
GC.Collect();
Assert.IsNotNull(item1);
Assert.IsFalse(weakList.TryGetTarget(out _));

(WeakReference<IList<CollectionEventsTestModel>> weakList, CollectionEventsTestModel item1) Core()
{
var list = factory();
return (new(list), list[0]);
}
}

[TestMethod]
public void CollectionItemChangedSpecialTest()
{
Original file line number Diff line number Diff line change
@@ -296,6 +296,16 @@ public void CollectionItemChangedTest()
ObservableListTest.CollectionItemChangedTestCore(list, listView);
}

[TestMethod]
public void CollectionItemChangedWeakTest()
{
ObservableListTest.CollectionItemChangedWeakCoreTest(() =>
{
var list = new ObservableList<CollectionEventsTestModel>(new[] { new CollectionEventsTestModel() });
return new ObservableListViewCore<CollectionEventsTestModel>(list);
});
}

[TestMethod]
public void RaiseEventsWithoutListener()
{
Original file line number Diff line number Diff line change
@@ -6,10 +6,12 @@
namespace System.Waf.Foundation
{
/// <summary>Represents a dynamic data collection that provides notifications when items get added or removed, or when the whole list is refreshed.
/// It extends the <see cref="ObservableCollection{T}"/> by implementing the <see cref="INotifyCollectionChanging"/> interface.</summary>
/// It extends the <see cref="ObservableCollection{T}"/> by implementing the <see cref="INotifyCollectionChanging"/> and the <see cref="INotifyCollectionItemChanged"/> interface.</summary>
/// <typeparam name="T">The type of elements in the collection.</typeparam>
public class ObservableList<T> : ObservableCollection<T>, IReadOnlyObservableList<T>
{
private readonly Dictionary<object, IWeakEventProxy> weakEventProxies = new();

/// <summary>Initializes a new instance of the <see cref="ObservableCollection{T}"/> class.</summary>
public ObservableList() { }

@@ -88,8 +90,19 @@ protected override void MoveItem(int oldIndex, int newIndex)

private void ItemPropertyChanged(object? sender, PropertyChangedEventArgs e) => OnCollectionItemChanged(sender, e);

private void TryAddItemPropertyChanged(T item) { if (item is INotifyPropertyChanged x) x.PropertyChanged += ItemPropertyChanged; }
private void TryAddItemPropertyChanged(T? item)
{
if (item is INotifyPropertyChanged x) weakEventProxies.Add(x, WeakEvent.PropertyChanged.Add(x, ItemPropertyChanged));
}

private void TryRemoveItemPropertyChanged(T item) { if (item is INotifyPropertyChanged x) x.PropertyChanged -= ItemPropertyChanged; }
private void TryRemoveItemPropertyChanged(T? item)
{
if (item is null) return;
if (weakEventProxies.TryGetValue(item, out var proxy))
{
proxy.Remove();
weakEventProxies.Remove(item);
}
}
}
}

0 comments on commit eb09d13

Please sign in to comment.