diff --git a/src/Avalonia.Base/PropertyStore/BindingEntry.cs b/src/Avalonia.Base/PropertyStore/BindingEntry.cs index 078b2b9d2e..2d4eb96736 100644 --- a/src/Avalonia.Base/PropertyStore/BindingEntry.cs +++ b/src/Avalonia.Base/PropertyStore/BindingEntry.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Reactive.Disposables; using Avalonia.Data; @@ -10,7 +9,6 @@ namespace Avalonia.PropertyStore IDisposable { private readonly ValueFrame _frame; - private readonly IObservable _source; private IDisposable? _subscription; private bool _hasValue; private object? _value; @@ -21,7 +19,7 @@ namespace Avalonia.PropertyStore IObservable source) { _frame = frame; - _source = source; + Source = source; Property = property; } @@ -35,6 +33,7 @@ namespace Avalonia.PropertyStore } public AvaloniaProperty Property { get; } + protected IObservable Source { get; } public void Dispose() { @@ -69,6 +68,18 @@ namespace Avalonia.PropertyStore _subscription = null; } + protected virtual void Start(bool produceValue) + { + if (_subscription is not null) + return; + + // Will only produce a new value when subscription isn't null. + if (produceValue) + _subscription = Disposable.Empty; + + _subscription = Source.Subscribe(this); + } + private void ClearValue() { if (_hasValue) @@ -123,17 +134,5 @@ namespace Avalonia.PropertyStore _subscription = null; _frame.OnBindingCompleted(this); } - - private void Start(bool produceValue) - { - if (_subscription is not null) - return; - - // Will only produce a new value when subscription isn't null. - if (produceValue) - _subscription = Disposable.Empty; - - _subscription = _source.Subscribe(this); - } } } diff --git a/src/Avalonia.Base/Styling/PropertySetterBindingInstance.cs b/src/Avalonia.Base/Styling/PropertySetterBindingInstance.cs index 18d23ab70b..4734033bef 100644 --- a/src/Avalonia.Base/Styling/PropertySetterBindingInstance.cs +++ b/src/Avalonia.Base/Styling/PropertySetterBindingInstance.cs @@ -7,7 +7,9 @@ namespace Avalonia.Styling { internal class PropertySetterBindingInstance : BindingEntry, ISetterInstance { - private readonly IDisposable? _twoWaySubscription; + private readonly AvaloniaObject _target; + private readonly BindingMode _mode; + private IDisposable? _twoWaySubscription; public PropertySetterBindingInstance( AvaloniaObject target, @@ -17,18 +19,14 @@ namespace Avalonia.Styling IObservable source) : base(instance, property, source) { - if (mode == BindingMode.TwoWay) + _target = target; + _mode = mode; + + if (mode == BindingMode.TwoWay && + source is not IObserver) { - // TODO: HUGE HACK FIXME - if (source is IObserver observer) - { - _twoWaySubscription = target.GetObservable(property).Skip(1).Subscribe(observer); - } - else - { - throw new NotSupportedException( - "Attempting to bind two-way with a binding source which doesn't support it."); - } + throw new NotSupportedException( + "Attempting to bind two-way with a binding source which doesn't support it."); } } @@ -37,5 +35,16 @@ namespace Avalonia.Styling _twoWaySubscription?.Dispose(); base.Unsubscribe(); } + + protected override void Start(bool produceValue) + { + if (_mode == BindingMode.TwoWay) + { + var observer = (IObserver)Source; + _twoWaySubscription = _target.GetObservable(Property).Skip(1).Subscribe(observer); + } + + base.Start(produceValue); + } } }