diff --git a/src/Avalonia.Base/Data/TemplateBinding.cs b/src/Avalonia.Base/Data/TemplateBinding.cs
index 09f04dfe70..0fd40cd09d 100644
--- a/src/Avalonia.Base/Data/TemplateBinding.cs
+++ b/src/Avalonia.Base/Data/TemplateBinding.cs
@@ -3,18 +3,21 @@ using System.Globalization;
using Avalonia.Data.Converters;
using Avalonia.Reactive;
using Avalonia.Styling;
+using Avalonia.Threading;
namespace Avalonia.Data
{
///
/// A XAML binding to a property on a control's templated parent.
///
- public class TemplateBinding : SingleSubscriberObservableBase,
+ public class TemplateBinding : IObservable,
IBinding,
IDescription,
IAvaloniaSubject,
- ISetterValue
+ ISetterValue,
+ IDisposable
{
+ private IObserver? _observer;
private bool _isSetterValue;
private StyledElement? _target;
private Type? _targetType;
@@ -29,6 +32,28 @@ namespace Avalonia.Data
Property = property;
}
+ public IDisposable Subscribe(IObserver observer)
+ {
+ _ = observer ?? throw new ArgumentNullException(nameof(observer));
+ Dispatcher.UIThread.VerifyAccess();
+
+ if (_observer != null)
+ {
+ throw new InvalidOperationException("The observable can only be subscribed once.");
+ }
+
+ _observer = observer;
+ Subscribed();
+
+ return this;
+ }
+
+ public virtual void Dispose()
+ {
+ Unsubscribed();
+ _observer = null;
+ }
+
///
public InstancedBinding? Initiate(
AvaloniaObject target,
@@ -111,7 +136,7 @@ namespace Avalonia.Data
///
void ISetterValue.Initialize(SetterBase setter) => _isSetterValue = true;
- protected override void Subscribed()
+ private void Subscribed()
{
TemplatedParentChanged();
@@ -121,7 +146,7 @@ namespace Avalonia.Data
}
}
- protected override void Unsubscribed()
+ private void Unsubscribed()
{
if (_target?.TemplatedParent is { } templatedParent)
{
@@ -147,12 +172,12 @@ namespace Avalonia.Data
value = Converter.Convert(value, _targetType ?? typeof(object), ConverterParameter, CultureInfo.CurrentCulture);
}
- PublishNext(value);
+ _observer?.OnNext(value);
_hasProducedValue = true;
}
else if (_hasProducedValue)
{
- PublishNext(AvaloniaProperty.UnsetValue);
+ _observer?.OnNext(AvaloniaProperty.UnsetValue);
_hasProducedValue = false;
}
}
diff --git a/src/Avalonia.Base/Reactive/SingleSubscriberObservableBase.cs b/src/Avalonia.Base/Reactive/SingleSubscriberObservableBase.cs
index 53a0b43c63..10d42214c2 100644
--- a/src/Avalonia.Base/Reactive/SingleSubscriberObservableBase.cs
+++ b/src/Avalonia.Base/Reactive/SingleSubscriberObservableBase.cs
@@ -3,7 +3,7 @@ using Avalonia.Threading;
namespace Avalonia.Reactive
{
- public abstract class SingleSubscriberObservableBase : IObservable, IDisposable
+ internal abstract class SingleSubscriberObservableBase : IObservable, IDisposable
{
private Exception? _error;
private IObserver? _observer;