From 3af6d2b3f01b2ae758f1e3f249cc4757e428e336 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 14 May 2024 15:39:23 +0200 Subject: [PATCH] Handle nested BindingNotifications. When #13970 was written, [a check](https://github.com/AvaloniaUI/Avalonia/pull/13970/files#diff-cfb25a491b9452e1815aa2c0d71465aaf81e99792a88a04a1a2ed572fd1930ffR60) was added to ensure that nested `BindingNotification`s didn't happen, and the refactor was written with the assumption that they wouldn't happen. The problem is that they _do_ happen: when a source object implements both `INotifyDataErrorInfo` and had data annotations, then the nested data validation plugins would each wrap the value coming from the previous plugin in a new `BindingNotification`, resulting in nested `BindingNotifications`. This adds support for nested binding notifications back in - even though IMO nesting binding notifications is a bug, if we're doing it and we previously supported it then we should continue to support it. Fixes #15201 --- src/Avalonia.Base/Data/BindingNotification.cs | 1 - .../Data/Core/ExpressionNodes/ExpressionNode.cs | 11 +++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Base/Data/BindingNotification.cs b/src/Avalonia.Base/Data/BindingNotification.cs index 0c940a14610..a3a2e0c2b05 100644 --- a/src/Avalonia.Base/Data/BindingNotification.cs +++ b/src/Avalonia.Base/Data/BindingNotification.cs @@ -57,7 +57,6 @@ public class BindingNotification /// The binding value. public BindingNotification(object? value) { - Debug.Assert(value is not BindingNotification); _value = value; } diff --git a/src/Avalonia.Base/Data/Core/ExpressionNodes/ExpressionNode.cs b/src/Avalonia.Base/Data/Core/ExpressionNodes/ExpressionNode.cs index e8e6633ab73..8b53190f869 100644 --- a/src/Avalonia.Base/Data/Core/ExpressionNodes/ExpressionNode.cs +++ b/src/Avalonia.Base/Data/Core/ExpressionNodes/ExpressionNode.cs @@ -187,13 +187,20 @@ protected void SetValue(object? valueOrNotification) else if (notification.ErrorType == BindingErrorType.DataValidationError) { if (notification.HasValue) - SetValue(notification.Value, notification.Error); + { + if (notification.Value is BindingNotification n) + SetValue(n); + else + SetValue(notification.Value, notification.Error); + } else + { SetDataValidationError(notification.Error!); + } } else { - SetValue(notification.Value, null); + SetValue(notification.Value); } } else