Browse Source

Merge pull request #8373 from AvaloniaUI/fixes/8372-clear-local-value

Correctly clear PriorityValue local value
pull/8383/head
Max Katz 4 years ago
committed by GitHub
parent
commit
138791e3e6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      src/Avalonia.Base/PropertyStore/PriorityValue.cs
  2. 27
      src/Avalonia.Base/Styling/PropertySetterInstance.cs
  3. 15
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetValue.cs
  4. 42
      tests/Avalonia.Base.UnitTests/Styling/SetterTests.cs

1
src/Avalonia.Base/PropertyStore/PriorityValue.cs

@ -121,6 +121,7 @@ namespace Avalonia.PropertyStore
public void ClearLocalValue() public void ClearLocalValue()
{ {
_localValue = default;
UpdateEffectiveValue(new AvaloniaPropertyChangedEventArgs<T>( UpdateEffectiveValue(new AvaloniaPropertyChangedEventArgs<T>(
_owner, _owner,
Property, Property,

27
src/Avalonia.Base/Styling/PropertySetterInstance.cs

@ -18,7 +18,7 @@ namespace Avalonia.Styling
private readonly DirectPropertyBase<T>? _directProperty; private readonly DirectPropertyBase<T>? _directProperty;
private readonly T _value; private readonly T _value;
private IDisposable? _subscription; private IDisposable? _subscription;
private bool _isActive; private State _state;
public PropertySetterInstance( public PropertySetterInstance(
IStyleable target, IStyleable target,
@ -40,6 +40,8 @@ namespace Avalonia.Styling
_value = value; _value = value;
} }
private bool IsActive => _state == State.Active;
public void Start(bool hasActivator) public void Start(bool hasActivator)
{ {
if (hasActivator) if (hasActivator)
@ -70,31 +72,35 @@ namespace Avalonia.Styling
public void Activate() public void Activate()
{ {
if (!_isActive) if (!IsActive)
{ {
_isActive = true; _state = State.Active;
PublishNext(); PublishNext();
} }
} }
public void Deactivate() public void Deactivate()
{ {
if (_isActive) if (IsActive)
{ {
_isActive = false; _state = State.Inactive;
PublishNext(); PublishNext();
} }
} }
public override void Dispose() public override void Dispose()
{ {
if (_state == State.Disposed)
return;
_state = State.Disposed;
if (_subscription is object) if (_subscription is object)
{ {
var sub = _subscription; var sub = _subscription;
_subscription = null; _subscription = null;
sub.Dispose(); sub.Dispose();
} }
else if (_isActive) else if (IsActive)
{ {
if (_styledProperty is object) if (_styledProperty is object)
{ {
@ -114,7 +120,14 @@ namespace Avalonia.Styling
private void PublishNext() private void PublishNext()
{ {
PublishNext(_isActive ? new BindingValue<T>(_value) : default); PublishNext(IsActive ? new BindingValue<T>(_value) : default);
}
private enum State
{
Inactive,
Active,
Disposed,
} }
} }
} }

15
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetValue.cs

@ -17,6 +17,21 @@ namespace Avalonia.Base.UnitTests
Assert.Equal("foodefault", target.GetValue(Class1.FooProperty)); Assert.Equal("foodefault", target.GetValue(Class1.FooProperty));
} }
[Fact]
public void ClearValue_Resets_Value_To_Style_value()
{
Class1 target = new Class1();
target.SetValue(Class1.FooProperty, "style", BindingPriority.Style);
target.SetValue(Class1.FooProperty, "local");
Assert.Equal("local", target.GetValue(Class1.FooProperty));
target.ClearValue(Class1.FooProperty);
Assert.Equal("style", target.GetValue(Class1.FooProperty));
}
[Fact] [Fact]
public void ClearValue_Raises_PropertyChanged() public void ClearValue_Raises_PropertyChanged()
{ {

42
tests/Avalonia.Base.UnitTests/Styling/SetterTests.cs

@ -150,13 +150,43 @@ namespace Avalonia.Base.UnitTests.Styling
Assert.Equal(BindingPriority.StyleTrigger, control.GetDiagnostic(TextBlock.TagProperty).Priority); Assert.Equal(BindingPriority.StyleTrigger, control.GetDiagnostic(TextBlock.TagProperty).Priority);
} }
private IBinding CreateMockBinding(AvaloniaProperty property) [Fact]
public void Disposing_Setter_Should_Preserve_LocalValue()
{ {
var subject = new Subject<object>(); var control = new Canvas();
var descriptor = InstancedBinding.OneWay(subject); var setter = new Setter(TextBlock.TagProperty, "foo");
var binding = Mock.Of<IBinding>(x =>
x.Initiate(It.IsAny<IAvaloniaObject>(), property, null, false) == descriptor); var instance = setter.Instance(control);
return binding; instance.Start(true);
instance.Activate();
control.Tag = "bar";
instance.Dispose();
Assert.Equal("bar", control.Tag);
}
[Fact]
public void Disposing_Binding_Setter_Should_Preserve_LocalValue()
{
var control = new Canvas();
var source = new { Foo = "foo" };
var setter = new Setter(TextBlock.TagProperty, new Binding
{
Source = source,
Path = nameof(source.Foo),
});
var instance = setter.Instance(control);
instance.Start(true);
instance.Activate();
control.Tag = "bar";
instance.Dispose();
Assert.Equal("bar", control.Tag);
} }
private class TestConverter : IValueConverter private class TestConverter : IValueConverter

Loading…
Cancel
Save