NotifyCollectionChangedExtensions.cs 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. using System;
  2. using System.Collections.Specialized;
  3. using Avalonia.Reactive;
  4. using Avalonia.Utilities;
  5. namespace Avalonia.Collections
  6. {
  7. public static class NotifyCollectionChangedExtensions
  8. {
  9. /// <summary>
  10. /// Gets a weak observable for the CollectionChanged event.
  11. /// </summary>
  12. /// <param name="collection">The collection.</param>
  13. /// <returns>An observable.</returns>
  14. public static IObservable<NotifyCollectionChangedEventArgs> GetWeakCollectionChangedObservable(
  15. this INotifyCollectionChanged collection)
  16. {
  17. _ = collection ?? throw new ArgumentNullException(nameof(collection));
  18. return new WeakCollectionChangedObservable(new WeakReference<INotifyCollectionChanged>(collection));
  19. }
  20. /// <summary>
  21. /// Subscribes to the CollectionChanged event using a weak subscription.
  22. /// </summary>
  23. /// <param name="collection">The collection.</param>
  24. /// <param name="handler">
  25. /// An action called when the collection event is raised.
  26. /// </param>
  27. /// <returns>A disposable used to terminate the subscription.</returns>
  28. public static IDisposable WeakSubscribe(
  29. this INotifyCollectionChanged collection,
  30. NotifyCollectionChangedEventHandler handler)
  31. {
  32. _ = collection ?? throw new ArgumentNullException(nameof(collection));
  33. _ = handler ?? throw new ArgumentNullException(nameof(handler));
  34. return collection.GetWeakCollectionChangedObservable()
  35. .Subscribe(e => handler(collection, e));
  36. }
  37. /// <summary>
  38. /// Subscribes to the CollectionChanged event using a weak subscription.
  39. /// </summary>
  40. /// <param name="collection">The collection.</param>
  41. /// <param name="handler">
  42. /// An action called when the collection event is raised.
  43. /// </param>
  44. /// <returns>A disposable used to terminate the subscription.</returns>
  45. public static IDisposable WeakSubscribe(
  46. this INotifyCollectionChanged collection,
  47. Action<NotifyCollectionChangedEventArgs> handler)
  48. {
  49. _ = collection ?? throw new ArgumentNullException(nameof(collection));
  50. _ = handler ?? throw new ArgumentNullException(nameof(handler));
  51. return collection.GetWeakCollectionChangedObservable().Subscribe(handler);
  52. }
  53. private class WeakCollectionChangedObservable : LightweightObservableBase<NotifyCollectionChangedEventArgs>,
  54. IWeakEventSubscriber<NotifyCollectionChangedEventArgs>
  55. {
  56. private WeakReference<INotifyCollectionChanged> _sourceReference;
  57. public WeakCollectionChangedObservable(WeakReference<INotifyCollectionChanged> source)
  58. {
  59. _sourceReference = source;
  60. }
  61. public void OnEvent(object? sender,
  62. WeakEvent ev,
  63. NotifyCollectionChangedEventArgs e)
  64. {
  65. PublishNext(e);
  66. }
  67. protected override void Initialize()
  68. {
  69. if (_sourceReference.TryGetTarget(out var instance))
  70. WeakEvents.CollectionChanged.Subscribe(instance, this);
  71. }
  72. protected override void Deinitialize()
  73. {
  74. if (_sourceReference.TryGetTarget(out var instance))
  75. WeakEvents.CollectionChanged.Unsubscribe(instance, this);
  76. }
  77. }
  78. }
  79. }