|
|
@@ -395,7 +395,7 @@ namespace Avalonia.PropertyStore
|
|
|
if (TryGetEffectiveValue(property, out var existing))
|
|
|
{
|
|
|
if (priority <= existing.BasePriority)
|
|
|
- ReevaluateEffectiveValue(property, existing);
|
|
|
+ ReevaluateEffectiveValue(property, existing, changedValueEntry: entry);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -774,6 +774,7 @@ namespace Avalonia.PropertyStore
|
|
|
private void ReevaluateEffectiveValue(
|
|
|
AvaloniaProperty property,
|
|
|
EffectiveValue? current,
|
|
|
+ IValueEntry? changedValueEntry = null,
|
|
|
bool ignoreLocalValue = false)
|
|
|
{
|
|
|
++_isEvaluating;
|
|
|
@@ -803,21 +804,11 @@ namespace Avalonia.PropertyStore
|
|
|
// effective values of all properties.
|
|
|
if (activeChanged && frame.EntryCount > 1)
|
|
|
{
|
|
|
- ReevaluateEffectiveValues();
|
|
|
+ ReevaluateEffectiveValues(changedValueEntry);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // We're interested in the value if:
|
|
|
- // - There is no current effective value, or
|
|
|
- // - The value's priority is higher than the current effective value's priority, or
|
|
|
- // - The value's priority is equal to the current effective value's priority, but the effective
|
|
|
- // value was set via SetCurrentValue, or
|
|
|
- // - The value is a non-animation value and its priority is higher than the current
|
|
|
- // effective value's base priority
|
|
|
- var isRelevantPriority = current is null ||
|
|
|
- (priority < current.Priority && priority < current.BasePriority) ||
|
|
|
- (priority == current.Priority && current.IsOverridenCurrentValue) ||
|
|
|
- (priority > BindingPriority.Animation && priority < current.BasePriority);
|
|
|
+ var isRelevantPriority = HasHigherPriority(entry!, priority, current, changedValueEntry);
|
|
|
|
|
|
if (foundEntry && isRelevantPriority && entry!.HasValue)
|
|
|
{
|
|
|
@@ -862,7 +853,7 @@ namespace Avalonia.PropertyStore
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void ReevaluateEffectiveValues()
|
|
|
+ private void ReevaluateEffectiveValues(IValueEntry? changedValueEntry = null)
|
|
|
{
|
|
|
++_isEvaluating;
|
|
|
|
|
|
@@ -897,10 +888,9 @@ namespace Avalonia.PropertyStore
|
|
|
{
|
|
|
var entry = frame.GetEntry(j);
|
|
|
var property = entry.Property;
|
|
|
-
|
|
|
- // Skip if we already have a value/base value for this property.
|
|
|
- if (_effectiveValues.TryGetValue(property, out var effectiveValue) &&
|
|
|
- effectiveValue.BasePriority < BindingPriority.Unset)
|
|
|
+ _effectiveValues.TryGetValue(property, out var effectiveValue);
|
|
|
+
|
|
|
+ if (!HasHigherPriority(entry, priority, effectiveValue, changedValueEntry))
|
|
|
continue;
|
|
|
|
|
|
if (!entry.HasValue)
|
|
|
@@ -945,6 +935,37 @@ namespace Avalonia.PropertyStore
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private static bool HasHigherPriority(
|
|
|
+ IValueEntry entry,
|
|
|
+ BindingPriority entryPriority,
|
|
|
+ EffectiveValue? current,
|
|
|
+ IValueEntry? changedValueEntry)
|
|
|
+ {
|
|
|
+ // Set the value if: there is no current effective value; or
|
|
|
+ if (current is null)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ // The value's priority is higher than the current effective value's priority; or
|
|
|
+ if (entryPriority < current.Priority && entryPriority < current.BasePriority)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ // - The value's priority is equal to the current effective value's priority
|
|
|
+ // - But the effective value was set via SetCurrentValue
|
|
|
+ // - As long as the SetCurrentValue wasn't overriding the value from the value entry under consideration
|
|
|
+ // - Or if it was, the value entry under consideration has changed; or
|
|
|
+ if (entryPriority == current.Priority &&
|
|
|
+ current.IsOverridenCurrentValue &&
|
|
|
+ (current.ValueEntry != entry || entry == changedValueEntry))
|
|
|
+ return true;
|
|
|
+
|
|
|
+ // The value is a non-animation value and its priority is higher than the current effective value's base
|
|
|
+ // priority.
|
|
|
+ if (entryPriority > BindingPriority.Animation && entryPriority < current.BasePriority)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
private bool TryGetEffectiveValue(
|
|
|
AvaloniaProperty property,
|
|
|
[NotNullWhen(true)] out EffectiveValue? value)
|