diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs index c619d80e23..34b209473b 100644 --- a/src/Avalonia.Base/AvaloniaObject.cs +++ b/src/Avalonia.Base/AvaloniaObject.cs @@ -82,6 +82,7 @@ namespace Avalonia set { + VerifyAccess(); if (_inheritanceParent != value) { if (_inheritanceParent != null) @@ -89,25 +90,33 @@ namespace Avalonia _inheritanceParent.InheritablePropertyChanged -= ParentPropertyChanged; } - var properties = AvaloniaPropertyRegistry.Instance.GetRegistered(this) - .Concat(AvaloniaPropertyRegistry.Instance.GetRegisteredAttached(this.GetType())); - var inherited = (from property in properties - where property.Inherits - select new - { - Property = property, - Value = GetValue(property), - }).ToList(); - + var oldInheritanceParent = _inheritanceParent; _inheritanceParent = value; + var valuestore = _values; - foreach (var i in inherited) + foreach (var property in AvaloniaPropertyRegistry.Instance.GetRegisteredInherited(GetType())) { - object newValue = GetValue(i.Property); + if (valuestore != null && valuestore.GetValue(property) != AvaloniaProperty.UnsetValue) + { + // if local value set there can be no change + continue; + } + // get the value as it would have been with the previous InheritanceParent + object oldValue; + if (oldInheritanceParent is AvaloniaObject aobj) + { + oldValue = aobj.GetValueOrDefaultUnchecked(property); + } + else + { + oldValue = ((IStyledPropertyAccessor)property).GetDefaultValue(GetType()); + } + + object newValue = GetDefaultValue(property); - if (!Equals(i.Value, newValue)) + if (!Equals(oldValue, newValue)) { - RaisePropertyChanged(i.Property, i.Value, newValue, BindingPriority.LocalValue); + RaisePropertyChanged(property, oldValue, newValue, BindingPriority.LocalValue); } } diff --git a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs index 88b0201fcb..d718f5917c 100644 --- a/src/Avalonia.Base/AvaloniaPropertyRegistry.cs +++ b/src/Avalonia.Base/AvaloniaPropertyRegistry.cs @@ -26,6 +26,8 @@ namespace Avalonia new Dictionary>(); private readonly Dictionary> _initializedCache = new Dictionary>(); + private readonly Dictionary> _inheritedCache = + new Dictionary>(); /// /// Gets the instance @@ -103,6 +105,46 @@ namespace Avalonia return result; } + /// + /// Gets all inherited s registered on a type. + /// + /// The type. + /// A collection of definitions. + public IEnumerable GetRegisteredInherited(Type type) + { + Contract.Requires(type != null); + + if (_inheritedCache.TryGetValue(type, out var result)) + { + return result; + } + + result = new List(); + var visited = new HashSet(); + + foreach (var property in GetRegistered(type)) + { + if (property.Inherits) + { + result.Add(property); + visited.Add(property); + } + } + foreach (var property in GetRegisteredAttached(type)) + { + if (property.Inherits) + { + if (!visited.Contains(property)) + { + result.Add(property); + } + } + } + + _inheritedCache.Add(type, result); + return result; + } + /// /// Gets all s registered on a object. /// @@ -230,6 +272,7 @@ namespace Avalonia _registeredCache.Clear(); _initializedCache.Clear(); + _inheritedCache.Clear(); } /// @@ -266,6 +309,7 @@ namespace Avalonia _attachedCache.Clear(); _initializedCache.Clear(); + _inheritedCache.Clear(); } internal void NotifyInitialized(AvaloniaObject o)