|
|
|
@ -7,6 +7,7 @@ using System.Reactive.Linq; |
|
|
|
using System.Reactive.Subjects; |
|
|
|
using Avalonia.Data.Converters; |
|
|
|
using Avalonia.Logging; |
|
|
|
using Avalonia.Reactive; |
|
|
|
using Avalonia.Utilities; |
|
|
|
|
|
|
|
namespace Avalonia.Data.Core |
|
|
|
@ -15,13 +16,14 @@ namespace Avalonia.Data.Core |
|
|
|
/// Binds to an expression on an object using a type value converter to convert the values
|
|
|
|
/// that are send and received.
|
|
|
|
/// </summary>
|
|
|
|
public class BindingExpression : ISubject<object>, IDescription |
|
|
|
public class BindingExpression : LightweightObservableBase<object>, ISubject<object>, IDescription |
|
|
|
{ |
|
|
|
private readonly ExpressionObserver _inner; |
|
|
|
private readonly Type _targetType; |
|
|
|
private readonly object _fallbackValue; |
|
|
|
private readonly BindingPriority _priority; |
|
|
|
private readonly Subject<object> _errors = new Subject<object>(); |
|
|
|
InnerListener _innerListener; |
|
|
|
WeakReference<object> _value; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="ExpressionObserver"/> class.
|
|
|
|
@ -139,7 +141,7 @@ namespace Avalonia.Data.Core |
|
|
|
"IValueConverter should not return non-errored BindingNotification."); |
|
|
|
} |
|
|
|
|
|
|
|
_errors.OnNext(notification); |
|
|
|
PublishNext(notification); |
|
|
|
|
|
|
|
if (_fallbackValue != AvaloniaProperty.UnsetValue) |
|
|
|
{ |
|
|
|
@ -170,12 +172,18 @@ namespace Avalonia.Data.Core |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
public IDisposable Subscribe(IObserver<object> observer) |
|
|
|
protected override void Initialize() => _innerListener = new InnerListener(this); |
|
|
|
protected override void Deinitialize() => _innerListener.Dispose(); |
|
|
|
|
|
|
|
protected override void Subscribed(IObserver<object> observer, bool first) |
|
|
|
{ |
|
|
|
return _inner.Select(ConvertValue).Merge(_errors).Subscribe(observer); |
|
|
|
if (!first && _value != null && _value.TryGetTarget(out var val) == true) |
|
|
|
{ |
|
|
|
observer.OnNext(val); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
private object ConvertValue(object value) |
|
|
|
{ |
|
|
|
var notification = value as BindingNotification; |
|
|
|
@ -301,5 +309,28 @@ namespace Avalonia.Data.Core |
|
|
|
|
|
|
|
return a; |
|
|
|
} |
|
|
|
|
|
|
|
public class InnerListener : IObserver<object>, IDisposable |
|
|
|
{ |
|
|
|
private readonly BindingExpression _owner; |
|
|
|
private readonly IDisposable _dispose; |
|
|
|
|
|
|
|
public InnerListener(BindingExpression owner) |
|
|
|
{ |
|
|
|
_owner = owner; |
|
|
|
_dispose = owner._inner.Subscribe(this); |
|
|
|
} |
|
|
|
|
|
|
|
public void Dispose() => _dispose.Dispose(); |
|
|
|
public void OnCompleted() => _owner.PublishCompleted(); |
|
|
|
public void OnError(Exception error) => _owner.PublishError(error); |
|
|
|
|
|
|
|
public void OnNext(object value) |
|
|
|
{ |
|
|
|
var converted = _owner.ConvertValue(value); |
|
|
|
_owner._value = new WeakReference<object>(converted); |
|
|
|
_owner.PublishNext(converted); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|