csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
3.1 KiB
87 lines
3.1 KiB
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Reactive.Linq;
|
|
using Avalonia.Utilities;
|
|
|
|
namespace Avalonia.Data.Core
|
|
{
|
|
public abstract class IndexerNodeBase : SettableNode
|
|
{
|
|
private IDisposable? _subscription;
|
|
|
|
protected override void StartListeningCore(WeakReference<object?> reference)
|
|
{
|
|
reference.TryGetTarget(out var target);
|
|
|
|
var incc = target as INotifyCollectionChanged;
|
|
var inpc = target as INotifyPropertyChanged;
|
|
var inputs = new List<IObservable<object?>>();
|
|
|
|
if (incc != null)
|
|
{
|
|
inputs.Add(WeakObservable.FromEventPattern(
|
|
incc, WeakEvents.CollectionChanged)
|
|
.Where(x => ShouldUpdate(x.Sender, x.EventArgs))
|
|
.Select(_ => GetValue(target)));
|
|
}
|
|
|
|
if (inpc != null)
|
|
{
|
|
inputs.Add(WeakObservable.FromEventPattern(
|
|
inpc, WeakEvents.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);
|
|
}
|
|
}
|
|
|