Browse Source

Merge branch 'master' into fixes/scroll-to-selected-item-listbox

danwalmsley 6 years ago
parent
commit
b3213a0432
2 changed files with 67 additions and 14 deletions
  1. 23 14
      src/Avalonia.Base/AvaloniaObject.cs
  2. 44 0
      src/Avalonia.Base/AvaloniaPropertyRegistry.cs

+ 23 - 14
src/Avalonia.Base/AvaloniaObject.cs

@@ -82,6 +82,7 @@ namespace Avalonia
 
 
             set
             set
             {
             {
+                VerifyAccess();
                 if (_inheritanceParent != value)
                 if (_inheritanceParent != value)
                 {
                 {
                     if (_inheritanceParent != null)
                     if (_inheritanceParent != null)
@@ -89,25 +90,33 @@ namespace Avalonia
                         _inheritanceParent.InheritablePropertyChanged -= ParentPropertyChanged;
                         _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;
                     _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);
                         }
                         }
                     }
                     }
 
 

+ 44 - 0
src/Avalonia.Base/AvaloniaPropertyRegistry.cs

@@ -26,6 +26,8 @@ namespace Avalonia
             new Dictionary<Type, List<AvaloniaProperty>>();
             new Dictionary<Type, List<AvaloniaProperty>>();
         private readonly Dictionary<Type, List<PropertyInitializationData>> _initializedCache =
         private readonly Dictionary<Type, List<PropertyInitializationData>> _initializedCache =
             new Dictionary<Type, List<PropertyInitializationData>>();
             new Dictionary<Type, List<PropertyInitializationData>>();
+        private readonly Dictionary<Type, List<AvaloniaProperty>> _inheritedCache =
+            new Dictionary<Type, List<AvaloniaProperty>>();
 
 
         /// <summary>
         /// <summary>
         /// Gets the <see cref="AvaloniaPropertyRegistry"/> instance
         /// Gets the <see cref="AvaloniaPropertyRegistry"/> instance
@@ -103,6 +105,46 @@ namespace Avalonia
             return result;
             return result;
         }
         }
 
 
+        /// <summary>
+        /// Gets all inherited <see cref="AvaloniaProperty"/>s registered on a type.
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns>
+        public IEnumerable<AvaloniaProperty> GetRegisteredInherited(Type type)
+        {
+            Contract.Requires<ArgumentNullException>(type != null);
+
+            if (_inheritedCache.TryGetValue(type, out var result))
+            {
+                return result;
+            }
+
+            result = new List<AvaloniaProperty>();
+            var visited = new HashSet<AvaloniaProperty>();
+
+            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;
+        }
+
         /// <summary>
         /// <summary>
         /// Gets all <see cref="AvaloniaProperty"/>s registered on a object.
         /// Gets all <see cref="AvaloniaProperty"/>s registered on a object.
         /// </summary>
         /// </summary>
@@ -230,6 +272,7 @@ namespace Avalonia
             
             
             _registeredCache.Clear();
             _registeredCache.Clear();
             _initializedCache.Clear();
             _initializedCache.Clear();
+            _inheritedCache.Clear();
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -266,6 +309,7 @@ namespace Avalonia
             
             
             _attachedCache.Clear();
             _attachedCache.Clear();
             _initializedCache.Clear();
             _initializedCache.Clear();
+            _inheritedCache.Clear();
         }
         }
 
 
         internal void NotifyInitialized(AvaloniaObject o)
         internal void NotifyInitialized(AvaloniaObject o)