diff --git a/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs index c03a384eee..ba4e60eb74 100644 --- a/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs @@ -52,11 +52,9 @@ namespace Avalonia.Data.Core.Plugins private class Accessor : PropertyAccessorBase, IWeakSubscriber { - 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.OnEvent(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == _property.Name || string.IsNullOrEmpty(e.PropertyName)) { _eventRaised = true; - _lastValue = CacheInvalid; SendCurrentValue(); } } diff --git a/src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs b/src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs index 4dbff4602f..efa5b88303 100644 --- a/src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs +++ b/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 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; + }); } } }