| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.ComponentModel;
- using System.Globalization;
- using System.Linq;
- using System.Reactive.Linq;
- using System.Reflection;
- using System.Text;
- using Avalonia.Data;
- using Avalonia.Utilities;
- namespace Avalonia.Data.Core
- {
- public abstract class IndexerNodeBase : SettableNode
- {
- private IDisposable _subscription;
-
- protected override void StartListeningCore(WeakReference reference)
- {
- var target = reference.Target;
- var incc = target as INotifyCollectionChanged;
- var inpc = target as INotifyPropertyChanged;
- var inputs = new List<IObservable<object>>();
- if (incc != null)
- {
- inputs.Add(WeakObservable.FromEventPattern<INotifyCollectionChanged, NotifyCollectionChangedEventArgs>(
- incc,
- nameof(incc.CollectionChanged))
- .Where(x => ShouldUpdate(x.Sender, x.EventArgs))
- .Select(_ => GetValue(target)));
- }
- if (inpc != null)
- {
- inputs.Add(WeakObservable.FromEventPattern<INotifyPropertyChanged, PropertyChangedEventArgs>(
- inpc,
- nameof(inpc.PropertyChanged))
- .Where(x => ShouldUpdate(x.Sender, x.EventArgs))
- .Select(_ => GetValue(target)));
- }
- _subscription = Observable.Merge(inputs).StartWith(GetValue(target)).Subscribe(ValueChanged);
- }
- protected override void StopListeningCore()
- {
- _subscription.Dispose();
- }
- protected abstract object GetValue(object target);
- protected abstract int? TryGetFirstArgumentAsInt();
- private bool ShouldUpdate(object sender, NotifyCollectionChangedEventArgs e)
- {
- if (sender is IList)
- {
- var index = TryGetFirstArgumentAsInt();
- if (index == null)
- {
- return false;
- }
- switch (e.Action)
- {
- case NotifyCollectionChangedAction.Add:
- return index >= e.NewStartingIndex;
- case NotifyCollectionChangedAction.Remove:
- return index >= e.OldStartingIndex;
- case NotifyCollectionChangedAction.Replace:
- return index >= e.NewStartingIndex &&
- index < e.NewStartingIndex + e.NewItems.Count;
- case NotifyCollectionChangedAction.Move:
- return (index >= e.NewStartingIndex &&
- index < e.NewStartingIndex + e.NewItems.Count) ||
- (index >= e.OldStartingIndex &&
- index < e.OldStartingIndex + e.OldItems.Count);
- case NotifyCollectionChangedAction.Reset:
- return true;
- }
- }
- return true; // Implementation defined meaning for the index, so just try to update anyway
- }
- protected abstract bool ShouldUpdate(object sender, PropertyChangedEventArgs e);
- }
- }
|