From cfd35d17d51a0d8c4136f0233285a856773f491e Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Feb 2023 11:18:38 +0100 Subject: [PATCH 1/2] Added failing `SetCurrentValue` test. `SetCurrent_Value_Persists_When_Toggling_Style_1` passes but `SetCurrent_Value_Persists_When_Toggling_Style_2` fails as it uses a different code-path. --- .../AvaloniaObjectTests_SetCurrentValue.cs | 81 ++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetCurrentValue.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetCurrentValue.cs index 8ad36a583e..c850fbdb08 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetCurrentValue.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetCurrentValue.cs @@ -1,6 +1,9 @@ using System; +using Avalonia.Controls; using Avalonia.Data; using Avalonia.Diagnostics; +using Avalonia.Styling; +using Avalonia.UnitTests; using Xunit; using Observable = Avalonia.Reactive.Observable; @@ -275,6 +278,79 @@ namespace Avalonia.Base.UnitTests Assert.Equal("style", target.Foo); } + [Fact] + public void SetCurrent_Value_Persists_When_Toggling_Style_1() + { + var target = new Class1(); + var root = new TestRoot(target) + { + Styles = + { + new Style(x => x.OfType().Class("foo")) + { + Setters = { new Setter(Class1.BarProperty, "bar") }, + } + } + }; + + root.LayoutManager.ExecuteInitialLayoutPass(); + + target.SetCurrentValue(Class1.FooProperty, "current"); + + Assert.Equal("current", target.Foo); + Assert.Equal("bardefault", target.Bar); + + target.Classes.Add("foo"); + + Assert.Equal("current", target.Foo); + Assert.Equal("bar", target.Bar); + + target.Classes.Remove("foo"); + + Assert.Equal("current", target.Foo); + Assert.Equal("bardefault", target.Bar); + } + + [Fact] + public void SetCurrent_Value_Persists_When_Toggling_Style_2() + { + var target = new Class1(); + var root = new TestRoot(target) + { + Styles = + { + new Style(x => x.OfType().Class("foo")) + { + Setters = + { + new Setter(Class1.BarProperty, "bar"), + new Setter(Class1.InheritedProperty, "inherited"), + }, + } + } + }; + + root.LayoutManager.ExecuteInitialLayoutPass(); + + target.SetCurrentValue(Class1.FooProperty, "current"); + + Assert.Equal("current", target.Foo); + Assert.Equal("bardefault", target.Bar); + Assert.Equal("inheriteddefault", target.Inherited); + + target.Classes.Add("foo"); + + Assert.Equal("current", target.Foo); + Assert.Equal("bar", target.Bar); + Assert.Equal("inherited", target.Inherited); + + target.Classes.Remove("foo"); + + Assert.Equal("current", target.Foo); + Assert.Equal("bardefault", target.Bar); + Assert.Equal("inheriteddefault", target.Inherited); + } + private BindingPriority GetPriority(AvaloniaObject target, AvaloniaProperty property) { return target.GetDiagnostic(property).Priority; @@ -285,16 +361,19 @@ namespace Avalonia.Base.UnitTests return target.GetDiagnostic(property).IsOverriddenCurrentValue; } - private class Class1 : AvaloniaObject + private class Class1 : Control { public static readonly StyledProperty FooProperty = AvaloniaProperty.Register(nameof(Foo), "foodefault"); + public static readonly StyledProperty BarProperty = + AvaloniaProperty.Register(nameof(Bar), "bardefault"); public static readonly StyledProperty InheritedProperty = AvaloniaProperty.Register(nameof(Inherited), "inheriteddefault", inherits: true); public static readonly StyledProperty CoercedProperty = AvaloniaProperty.Register(nameof(Coerced), coerce: Coerce); public string Foo => GetValue(FooProperty); + public string Bar => GetValue(BarProperty); public string Inherited => GetValue(InheritedProperty); public double Coerced => GetValue(CoercedProperty); public double CoerceMax { get; set; } = 100; From d84f8225bee13c50060b79304273a1d2fd4ab548 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Feb 2023 11:21:01 +0100 Subject: [PATCH 2/2] Fix value re-evaluation with SetCurrentValue. `SetCurrentValue`'s value was being discarded if a style with more than one setter was was re-evaluated as `ValueStore.ReevaluationEffectiveValues` removed the effective value. --- src/Avalonia.Base/PropertyStore/ValueStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Base/PropertyStore/ValueStore.cs b/src/Avalonia.Base/PropertyStore/ValueStore.cs index 0887f11ec9..53cd3ff307 100644 --- a/src/Avalonia.Base/PropertyStore/ValueStore.cs +++ b/src/Avalonia.Base/PropertyStore/ValueStore.cs @@ -924,7 +924,7 @@ namespace Avalonia.PropertyStore { _effectiveValues.GetKeyValue(i, out var key, out var e); - if (e.Priority == BindingPriority.Unset) + if (e.Priority == BindingPriority.Unset && !e.IsOverridenCurrentValue) { RemoveEffectiveValue(key, i); e.DisposeAndRaiseUnset(this, key);