diff --git a/src/Avalonia.Base/PriorityValue.cs b/src/Avalonia.Base/PriorityValue.cs index df138c88f5..3930b6c224 100644 --- a/src/Avalonia.Base/PriorityValue.cs +++ b/src/Avalonia.Base/PriorityValue.cs @@ -235,75 +235,56 @@ namespace Avalonia /// The priority level that the value came from. private void UpdateValue(object value, int priority) { - if (!delayedSetter.IsNotifying(this)) + delayedSetter.SetAndNotify(this, (update, notify) => { - value = UpdateValueCore(value, priority); + var val = update.value; + var notification = val as BindingNotification; + object castValue; - while (delayedSetter.HasPendingSet(this)) + if (notification != null) { - var pendingSet = delayedSetter.GetFirstPendingSet(this); - UpdateValueCore(pendingSet.value, pendingSet.priority); + val = (notification.HasValue) ? notification.Value : null; } - } - else if(!object.Equals(value, _value)) - { - delayedSetter.AddPendingSet(this, (value, priority)); - } - } - - private object UpdateValueCore(object value, int priority) - { - var notification = value as BindingNotification; - object castValue; - if (notification != null) - { - value = (notification.HasValue) ? notification.Value : null; - } + if (TypeUtilities.TryConvertImplicit(_valueType, val, out castValue)) + { + var old = _value; - if (TypeUtilities.TryConvertImplicit(_valueType, value, out castValue)) - { - var old = _value; + if (_validate != null && castValue != AvaloniaProperty.UnsetValue) + { + castValue = _validate(castValue); + } - if (_validate != null && castValue != AvaloniaProperty.UnsetValue) - { - castValue = _validate(castValue); - } + ValuePriority = priority; + _value = castValue; - ValuePriority = priority; - _value = castValue; + if (notification?.HasValue == true) + { + notification.SetValue(castValue); + } - if (notification?.HasValue == true) - { - notification.SetValue(castValue); - } + if (notification == null || notification.HasValue) + { + notify(() => Owner?.Changed(this, old, _value)); + } - if (notification == null || notification.HasValue) - { - using (delayedSetter.MarkNotifying(this)) + if (notification != null) { - Owner?.Changed(this, old, _value); + Owner?.BindingNotificationReceived(this, notification); } } - - if (notification != null) + else { - Owner?.BindingNotificationReceived(this, notification); + Logger.Error( + LogArea.Binding, + Owner, + "Binding produced invalid value for {$Property} ({$PropertyType}): {$Value} ({$ValueType})", + Property.Name, + _valueType, + val, + val?.GetType()); } - } - else - { - Logger.Error( - LogArea.Binding, - Owner, - "Binding produced invalid value for {$Property} ({$PropertyType}): {$Value} ({$ValueType})", - Property.Name, - _valueType, - value, - value?.GetType()); - } - - return value; + }, (value, priority), val => !object.Equals(val.value, _value)); } } } diff --git a/src/Avalonia.Base/Utilities/DelayedSetter.cs b/src/Avalonia.Base/Utilities/DelayedSetter.cs index 6d611dfa46..155e4509a2 100644 --- a/src/Avalonia.Base/Utilities/DelayedSetter.cs +++ b/src/Avalonia.Base/Utilities/DelayedSetter.cs @@ -58,7 +58,7 @@ namespace Avalonia.Utilities return setRecords[property].PendingValues.Dequeue(); } - public void SetAndNotify(T property, Action> setterCallback, TValue value) + public void SetAndNotify(T property, Action> setterCallback, TValue value, Predicate pendingSetCondition) { Contract.Requires(setterCallback != null); if (!IsNotifying(property)) @@ -81,10 +81,13 @@ namespace Avalonia.Utilities }); } } - else + else if(pendingSetCondition?.Invoke(value) ?? true) { AddPendingSet(property, value); } } + + public void SetAndNotify(T property, Action> setterCallback, TValue value) + => SetAndNotify(property, setterCallback, value, null); } }