4 changed files with 146 additions and 10 deletions
@ -0,0 +1,128 @@ |
|||||
|
using System; |
||||
|
using Avalonia.Data; |
||||
|
using Avalonia.Reactive; |
||||
|
|
||||
|
#nullable enable |
||||
|
|
||||
|
namespace Avalonia.Styling |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A <see cref="Setter"/> which has been instanced on a control and whose value is lazily
|
||||
|
/// evaluated.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The target property type.</typeparam>
|
||||
|
internal class PropertySetterLazyInstance<T> : SingleSubscriberObservableBase<BindingValue<T>>, |
||||
|
ISetterInstance |
||||
|
{ |
||||
|
private readonly IStyleable _target; |
||||
|
private readonly StyledPropertyBase<T>? _styledProperty; |
||||
|
private readonly DirectPropertyBase<T>? _directProperty; |
||||
|
private readonly Func<T> _valueFactory; |
||||
|
private BindingValue<T> _value; |
||||
|
private IDisposable? _subscription; |
||||
|
private bool _isActive; |
||||
|
|
||||
|
public PropertySetterLazyInstance( |
||||
|
IStyleable target, |
||||
|
StyledPropertyBase<T> property, |
||||
|
Func<T> valueFactory) |
||||
|
{ |
||||
|
_target = target; |
||||
|
_styledProperty = property; |
||||
|
_valueFactory = valueFactory; |
||||
|
} |
||||
|
|
||||
|
public PropertySetterLazyInstance( |
||||
|
IStyleable target, |
||||
|
DirectPropertyBase<T> property, |
||||
|
Func<T> valueFactory) |
||||
|
{ |
||||
|
_target = target; |
||||
|
_directProperty = property; |
||||
|
_valueFactory = valueFactory; |
||||
|
} |
||||
|
|
||||
|
public void Start(bool hasActivator) |
||||
|
{ |
||||
|
_isActive = !hasActivator; |
||||
|
|
||||
|
if (_styledProperty is object) |
||||
|
{ |
||||
|
var priority = hasActivator ? BindingPriority.StyleTrigger : BindingPriority.Style; |
||||
|
_subscription = _target.Bind(_styledProperty, this, priority); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
_subscription = _target.Bind(_directProperty, this); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Activate() |
||||
|
{ |
||||
|
if (!_isActive) |
||||
|
{ |
||||
|
_isActive = true; |
||||
|
PublishNext(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void Deactivate() |
||||
|
{ |
||||
|
if (_isActive) |
||||
|
{ |
||||
|
_isActive = false; |
||||
|
PublishNext(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void Dispose() |
||||
|
{ |
||||
|
if (_subscription is object) |
||||
|
{ |
||||
|
var sub = _subscription; |
||||
|
_subscription = null; |
||||
|
sub.Dispose(); |
||||
|
} |
||||
|
else if (_isActive) |
||||
|
{ |
||||
|
if (_styledProperty is object) |
||||
|
{ |
||||
|
_target.ClearValue(_styledProperty); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
_target.ClearValue(_directProperty); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
base.Dispose(); |
||||
|
} |
||||
|
|
||||
|
protected override void Subscribed() => PublishNext(); |
||||
|
protected override void Unsubscribed() { } |
||||
|
|
||||
|
private T GetValue() |
||||
|
{ |
||||
|
if (_value.HasValue) |
||||
|
{ |
||||
|
return _value.Value; |
||||
|
} |
||||
|
|
||||
|
_value = _valueFactory(); |
||||
|
return _value.Value; |
||||
|
} |
||||
|
|
||||
|
private void PublishNext() |
||||
|
{ |
||||
|
if (_isActive) |
||||
|
{ |
||||
|
GetValue(); |
||||
|
PublishNext(_value); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
PublishNext(default); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue