diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs index 7a35fc89b7..2e1944fc76 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Reactive.Subjects; using Avalonia.Data; using Xunit; @@ -52,6 +53,64 @@ namespace Avalonia.Base.UnitTests Assert.Equal(50, target.Foo); } + [Fact] + public void CoerceValue_Updates_Base_Value() + { + var target = new Class1 { Foo = 99 }; + + target.SetValue(Class1.FooProperty, 88, BindingPriority.Animation); + + Assert.Equal(88, target.Foo); + Assert.Equal(99, target.GetBaseValue(Class1.FooProperty)); + + target.MaxFoo = 50; + target.CoerceValue(Class1.FooProperty); + + Assert.Equal(50, target.Foo); + Assert.Equal(50, target.GetBaseValue(Class1.FooProperty)); + } + + [Fact] + public void CoerceValue_Raises_PropertyChanged() + { + var target = new Class1 { Foo = 99 }; + var raised = 0; + + target.PropertyChanged += (s, e) => + { + Assert.Equal(Class1.FooProperty, e.Property); + Assert.Equal(99, e.OldValue); + Assert.Equal(50, e.NewValue); + Assert.Equal(BindingPriority.LocalValue, e.Priority); + ++raised; + }; + + Assert.Equal(99, target.Foo); + + target.MaxFoo = 50; + target.CoerceValue(Class1.FooProperty); + + Assert.Equal(50, target.Foo); + Assert.Equal(1, raised); + } + + [Fact] + public void CoerceValue_Raises_PropertyChangedCore_For_Base_Value() + { + var target = new Class1 { Foo = 99 }; + + target.SetValue(Class1.FooProperty, 88, BindingPriority.Animation); + + Assert.Equal(88, target.Foo); + Assert.Equal(99, target.GetBaseValue(Class1.FooProperty)); + + target.MaxFoo = 50; + target.CoreChanges.Clear(); + target.CoerceValue(Class1.FooProperty); + + Assert.Equal(2, target.CoreChanges.Count); + } + [Fact] public void Coerced_Value_Can_Be_Restored_If_Limit_Changed() { @@ -87,6 +146,32 @@ namespace Avalonia.Base.UnitTests Assert.Equal(150, target.Foo); } + [Fact] + public void CoerceValue_Updates_Inherited_Value() + { + var parent = new Class1 { Inherited = 99 }; + var child = new AvaloniaObject { InheritanceParent = parent }; + var raised = 0; + + child.InheritanceParent = parent; + child.PropertyChanged += (s, e) => + { + Assert.Equal(Class1.InheritedProperty, e.Property); + Assert.Equal(99, e.OldValue); + Assert.Equal(50, e.NewValue); + Assert.Equal(BindingPriority.Inherited, e.Priority); + ++raised; + }; + + Assert.Equal(99, child.GetValue(Class1.InheritedProperty)); + + parent.MaxFoo = 50; + parent.CoerceValue(Class1.InheritedProperty); + + Assert.Equal(50, child.GetValue(Class1.InheritedProperty)); + Assert.Equal(1, raised); + } + [Fact] public void Coercion_Can_Be_Overridden() { @@ -111,18 +196,51 @@ namespace Avalonia.Base.UnitTests defaultValue: 11, coerce: CoerceFoo); + public static readonly StyledProperty InheritedProperty = + AvaloniaProperty.RegisterAttached( + "Attached", + defaultValue: 11, + inherits: true, + coerce: CoerceFoo); + public int Foo { get => GetValue(FooProperty); set => SetValue(FooProperty, value); } + public int Inherited + { + get => GetValue(InheritedProperty); + set => SetValue(InheritedProperty, value); + } + public int MaxFoo { get; set; } = 100; + public List CoreChanges { get; } = new(); + public static int CoerceFoo(IAvaloniaObject instance, int value) { return Math.Min(((Class1)instance).MaxFoo, value); } + + protected override void OnPropertyChangedCore(AvaloniaPropertyChangedEventArgs change) + { + CoreChanges.Add(Clone(change)); + base.OnPropertyChangedCore(change); + } + + private static AvaloniaPropertyChangedEventArgs Clone(AvaloniaPropertyChangedEventArgs change) + { + var e = (AvaloniaPropertyChangedEventArgs)change; + return new AvaloniaPropertyChangedEventArgs( + change.Sender, + e.Property, + e.OldValue, + e.NewValue, + change.Priority, + change.IsEffectiveValueChange); + } } private class Class2 : AvaloniaObject