Browse Source

Move fix up to PropertyAccessorNode from InpcPropertyAccessorPlugin.

Jeremy Koritzinsky 7 years ago
parent
commit
41b20f63f0

+ 1 - 21
src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs

@@ -52,11 +52,9 @@ namespace Avalonia.Data.Core.Plugins
 
         private class Accessor : PropertyAccessorBase, IWeakSubscriber<PropertyChangedEventArgs>
         {
-            private static readonly object CacheInvalid = new object();
             private readonly WeakReference _reference;
             private readonly PropertyInfo _property;
             private bool _eventRaised;
-            private object _lastValue = CacheInvalid;
 
             public Accessor(WeakReference reference,  PropertyInfo property)
             {
@@ -74,7 +72,7 @@ namespace Avalonia.Data.Core.Plugins
                 get
                 {
                     var o = _reference.Target;
-                    return (_lastValue = (o != null) ? _property.GetValue(o) : null);
+                    return (o != null) ? _property.GetValue(o) : null;
                 }
             }
 
@@ -82,11 +80,6 @@ namespace Avalonia.Data.Core.Plugins
             {
                 if (_property.CanWrite)
                 {
-                    if (!ShouldSet(value))
-                    {
-                        return true;
-                    }
-
                     _eventRaised = false;
                     _property.SetValue(_reference.Target, value);
 
@@ -101,24 +94,11 @@ namespace Avalonia.Data.Core.Plugins
                 return false;
             }
 
-            private bool ShouldSet(object value)
-            {
-                if (PropertyType.IsValueType)
-                {
-                    return !_lastValue.Equals(value);
-                }
-                else
-                {
-                    return !Object.ReferenceEquals(_lastValue, value);
-                }
-            }
-
             void IWeakSubscriber<PropertyChangedEventArgs>.OnEvent(object sender, PropertyChangedEventArgs e)
             {
                 if (e.PropertyName == _property.Name || string.IsNullOrEmpty(e.PropertyName))
                 {
                     _eventRaised = true;
-                    _lastValue = CacheInvalid;
                     SendCurrentValue();
                 }
             }

+ 35 - 2
src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs

@@ -12,8 +12,10 @@ namespace Avalonia.Data.Core
 {
     internal class PropertyAccessorNode : ExpressionNode, ISettableNode
     {
+        private static readonly object CacheInvalid = new object();
         private readonly bool _enableValidation;
         private IPropertyAccessor _accessor;
+        private object _lastValue = CacheInvalid;
 
         public PropertyAccessorNode(string propertyName, bool enableValidation)
         {
@@ -29,12 +31,32 @@ namespace Avalonia.Data.Core
         {
             if (_accessor != null)
             {
-                try { return _accessor.SetValue(value, priority); } catch { }
+                try
+                {
+                    if (ShouldNotSet(value))
+                    {
+                        return true;
+                    }
+                    else
+                    {
+                        return _accessor.SetValue(value, priority);
+                    }
+                }
+                catch { }
             }
 
             return false;
         }
 
+        private bool ShouldNotSet(object value)
+        {
+            if (PropertyType.IsValueType)
+            {
+                return _lastValue.Equals(value);
+            }
+            return Object.ReferenceEquals(_lastValue, value);
+        }
+
         protected override IObservable<object> StartListeningCore(WeakReference reference)
         {
             var plugin = ExpressionObserver.PropertyAccessors.FirstOrDefault(x => x.Match(reference.Target, PropertyName));
@@ -58,7 +80,18 @@ namespace Avalonia.Data.Core
                     _accessor = accessor;
                     return Disposable.Create(() => _accessor = null);
                 },
-                _ => accessor);
+                _ => accessor).Select(value =>
+                {
+                    if (value is BindingNotification notification)
+                    {
+                        _lastValue = notification.HasValue ? notification.Value : CacheInvalid; 
+                    }
+                    else
+                    {
+                        _lastValue = value;
+                    }
+                    return value;
+                });
         }
     }
 }