From 959d0cce1ea2afbbad7e56db76d30830bfd1e862 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 28 Apr 2020 10:59:53 +0200 Subject: [PATCH] Don't notify AvaloniaProperty.Changed on non-effective value change. --- src/Avalonia.Base/AvaloniaObject.cs | 6 +++++- .../AvaloniaPropertyChangedEventArgs.cs | 2 +- src/Avalonia.Base/PropertyStore/PriorityValue.cs | 2 +- .../AvaloniaPropertyTests.cs | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs index 073cedbb1c..479ce54ea0 100644 --- a/src/Avalonia.Base/AvaloniaObject.cs +++ b/src/Avalonia.Base/AvaloniaObject.cs @@ -769,7 +769,11 @@ namespace Avalonia try { OnPropertyChangedCore(change); - change.Property.NotifyChanged(change); + + if (change.IsEffectiveValueChange && !change.IsOutdated) + { + change.Property.NotifyChanged(change); + } if (_listeners is object && _listeners.TryGetValue(change.Property, out var listener)) { diff --git a/src/Avalonia.Base/AvaloniaPropertyChangedEventArgs.cs b/src/Avalonia.Base/AvaloniaPropertyChangedEventArgs.cs index 94aa8baa32..3bdcbf8ff4 100644 --- a/src/Avalonia.Base/AvaloniaPropertyChangedEventArgs.cs +++ b/src/Avalonia.Base/AvaloniaPropertyChangedEventArgs.cs @@ -80,7 +80,7 @@ namespace Avalonia public bool IsOutdated { get; private set; } internal void MarkOutdated() => IsOutdated = true; - internal void MarkInactiveValue() => IsEffectiveValueChange = false; + internal void MarkNonEffectiveValue() => IsEffectiveValueChange = false; protected abstract AvaloniaProperty GetProperty(); protected abstract object? GetOldValue(); protected abstract object? GetNewValue(); diff --git a/src/Avalonia.Base/PropertyStore/PriorityValue.cs b/src/Avalonia.Base/PropertyStore/PriorityValue.cs index 599dfdb8ad..5e223cad60 100644 --- a/src/Avalonia.Base/PropertyStore/PriorityValue.cs +++ b/src/Avalonia.Base/PropertyStore/PriorityValue.cs @@ -250,7 +250,7 @@ namespace Avalonia.PropertyStore } else if (change is object) { - change.MarkInactiveValue(); + change.MarkNonEffectiveValue(); change.SetOldValue(default); _sink.ValueChanged(change); } diff --git a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs index b235655e61..0da35ac65c 100644 --- a/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs +++ b/tests/Avalonia.Base.UnitTests/AvaloniaPropertyTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Avalonia.Data; using Avalonia.Utilities; using Xunit; @@ -88,6 +89,19 @@ namespace Avalonia.Base.UnitTests Assert.Equal("newvalue", value); } + [Fact] + public void Changed_Observable_Fired_Only_On_Effective_Value_Change() + { + var target = new Class1(); + var result = new List(); + + Class1.FooProperty.Changed.Subscribe(x => result.Add((string)x.NewValue)); + target.SetValue(Class1.FooProperty, "animated", BindingPriority.Animation); + target.SetValue(Class1.FooProperty, "local"); + + Assert.Equal(new[] { "animated" }, result); + } + [Fact] public void Property_Equals_Should_Handle_Null() {