// Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; using System.Collections.Specialized; using System.Reactive.Linq; using Avalonia.Reactive; using Avalonia.Utilities; namespace Avalonia.Collections { public static class NotifyCollectionChangedExtensions { /// /// Gets a weak observable for the CollectionChanged event. /// /// The collection. /// An observable. public static IObservable GetWeakCollectionChangedObservable( this INotifyCollectionChanged collection) { Contract.Requires(collection != null); return new WeakCollectionChangedObservable(new WeakReference(collection)); } /// /// Subscribes to the CollectionChanged event using a weak subscription. /// /// The collection. /// /// An action called when the collection event is raised. /// /// A disposable used to terminate the subscription. public static IDisposable WeakSubscribe( this INotifyCollectionChanged collection, NotifyCollectionChangedEventHandler handler) { Contract.Requires(collection != null); Contract.Requires(handler != null); return collection.GetWeakCollectionChangedObservable() .Subscribe(e => handler(collection, e)); } /// /// Subscribes to the CollectionChanged event using a weak subscription. /// /// The collection. /// /// An action called when the collection event is raised. /// /// A disposable used to terminate the subscription. public static IDisposable WeakSubscribe( this INotifyCollectionChanged collection, Action handler) { Contract.Requires(collection != null); Contract.Requires(handler != null); return collection.GetWeakCollectionChangedObservable().Subscribe(handler); } private class WeakCollectionChangedObservable : LightweightObservableBase, IWeakSubscriber { private WeakReference _sourceReference; public WeakCollectionChangedObservable(WeakReference source) { _sourceReference = source; } public void OnEvent(object sender, NotifyCollectionChangedEventArgs e) { PublishNext(e); } protected override void Initialize() { if (_sourceReference.TryGetTarget(out INotifyCollectionChanged instance)) { WeakSubscriptionManager.Subscribe( instance, nameof(instance.CollectionChanged), this); } } protected override void Deinitialize() { if (_sourceReference.TryGetTarget(out INotifyCollectionChanged instance)) { WeakSubscriptionManager.Unsubscribe( instance, nameof(instance.CollectionChanged), this); } } } } }