diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index 83b0d4e533..be7a14dcf9 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -464,7 +464,7 @@ namespace Avalonia
///
void IPriorityValueOwner.BindingNotificationReceived(PriorityValue sender, BindingNotification notification)
{
- BindingNotificationReceived(sender.Property, notification);
+ UpdateDataValidation(sender.Property, notification);
}
///
@@ -499,14 +499,16 @@ namespace Avalonia
}
///
- /// Occurs when a is received for a property which has
- /// data validation enabled.
+ /// Called to update the validation state for properties for which data validation is
+ /// enabled.
///
/// The property.
- /// The binding notification.
- protected virtual void BindingNotificationReceived(
+ ///
+ /// The new validation status. A value of null indicates no validation error.
+ ///
+ protected virtual void UpdateDataValidation(
AvaloniaProperty property,
- BindingNotification notification)
+ BindingNotification status)
{
}
@@ -647,20 +649,12 @@ namespace Avalonia
///
private void DirectBindingSet(AvaloniaProperty property, object value)
{
+ var validated = property.GetMetadata(GetType()).EnableDataValidation;
var notification = value as BindingNotification;
- if (notification == null)
- {
- SetValue(property, value);
- }
- else
+ if (notification != null)
{
- if (notification.HasValue)
- {
- SetValue(property, notification.Value);
- }
-
- BindingNotificationReceived(property, notification);
+ value = notification.Value;
if (notification.ErrorType == BindingErrorType.Error)
{
@@ -673,6 +667,16 @@ namespace Avalonia
ExceptionUtilities.GetMessage(notification.Error));
}
}
+
+ if (notification?.HasValue != false)
+ {
+ SetValue(property, value);
+ }
+
+ if (validated)
+ {
+ UpdateDataValidation(property, notification);
+ }
}
///
diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/DataValidatiorBase.cs b/src/Markup/Avalonia.Markup/Data/Plugins/DataValidatiorBase.cs
index 95d269f437..9b387456ca 100644
--- a/src/Markup/Avalonia.Markup/Data/Plugins/DataValidatiorBase.cs
+++ b/src/Markup/Avalonia.Markup/Data/Plugins/DataValidatiorBase.cs
@@ -68,13 +68,11 @@ namespace Avalonia.Markup.Data.Plugins
///
/// The value.
///
- /// Notifies the observer that the value has changed. The value will be wrapped in a
- /// if it is not already a binding notification.
+ /// Notifies the observer that the value has changed.
///
protected virtual void InnerValueChanged(object value)
{
- var notification = value as BindingNotification ?? new BindingNotification(value);
- Observer.OnNext(notification);
+ Observer.OnNext(value);
}
}
}
\ No newline at end of file
diff --git a/src/Markup/Avalonia.Markup/Data/Plugins/IndeiValidationPlugin.cs b/src/Markup/Avalonia.Markup/Data/Plugins/IndeiValidationPlugin.cs
index 8fb2568f30..561bd66db3 100644
--- a/src/Markup/Avalonia.Markup/Data/Plugins/IndeiValidationPlugin.cs
+++ b/src/Markup/Avalonia.Markup/Data/Plugins/IndeiValidationPlugin.cs
@@ -40,7 +40,7 @@ namespace Avalonia.Markup.Data.Plugins
{
if (e.PropertyName == _name || string.IsNullOrEmpty(e.PropertyName))
{
- Observer.OnNext(CreateBindingNotification(Value));
+ Observer.OnNext(BuildResult(Value));
}
}
@@ -76,10 +76,10 @@ namespace Avalonia.Markup.Data.Plugins
protected override void InnerValueChanged(object value)
{
- base.InnerValueChanged(CreateBindingNotification(value));
+ base.InnerValueChanged(BuildResult(value));
}
- private BindingNotification CreateBindingNotification(object value)
+ private object BuildResult(object value)
{
var target = (INotifyDataErrorInfo)_reference.Target;
@@ -98,7 +98,7 @@ namespace Avalonia.Markup.Data.Plugins
}
}
- return new BindingNotification(value);
+ return value;
}
private Exception GenerateException(IList errors)
diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_DataValidation.cs b/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_DataValidation.cs
index cdcaeda4cc..a363d69486 100644
--- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_DataValidation.cs
+++ b/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_DataValidation.cs
@@ -81,16 +81,16 @@ namespace Avalonia.Markup.UnitTests.Data
observer.SetValue("foo");
observer.SetValue(5);
- Assert.Equal(new[]
+ Assert.Equal(new object[]
{
- new BindingNotification(0),
+ 0,
// Value is notified twice as ErrorsChanged is always called by IndeiTest.
- new BindingNotification(5),
- new BindingNotification(5),
+ 5,
+ 5,
// Value is first signalled without an error as validation hasn't been updated.
- new BindingNotification(-5),
+ -5,
new BindingNotification(new Exception("Must be positive"), BindingErrorType.DataValidationError, -5),
// Exception is thrown by trying to set value to "foo".
@@ -100,7 +100,7 @@ namespace Avalonia.Markup.UnitTests.Data
// Value is set then validation is updated.
new BindingNotification(new Exception("Must be positive"), BindingErrorType.DataValidationError, 5),
- new BindingNotification(5),
+ 5,
}, result);
}
diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Observable.cs b/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Observable.cs
index 3263aaace2..3b915f97a8 100644
--- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Observable.cs
+++ b/tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Observable.cs
@@ -85,7 +85,7 @@ namespace Avalonia.Markup.UnitTests.Data
data.Next.OnNext(new Class2("foo"));
sync.ExecutePostedCallbacks();
- Assert.Equal(new[] { new BindingNotification("foo") }, result);
+ Assert.Equal(new[] { "foo" }, result);
sub.Dispose();
Assert.Equal(0, data.PropertyChangedSubscriptionCount);
diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionSubjectTests.cs b/tests/Avalonia.Markup.UnitTests/Data/ExpressionSubjectTests.cs
index 5498926fe4..16b71c87fe 100644
--- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionSubjectTests.cs
+++ b/tests/Avalonia.Markup.UnitTests/Data/ExpressionSubjectTests.cs
@@ -288,11 +288,11 @@ namespace Avalonia.Markup.UnitTests.Data
target.OnNext("bar");
Assert.Equal(
- new[]
+ new object[]
{
- new BindingNotification("5.6"),
- new BindingNotification("1.2"),
- new BindingNotification("3.4"),
+ "5.6",
+ "1.2",
+ "3.4",
new BindingNotification(
new InvalidCastException("Error setting 'DoubleValue': Could not convert 'bar' to 'System.Double'"),
BindingErrorType.Error)
diff --git a/tests/Avalonia.Markup.UnitTests/Data/Plugins/ExceptionValidationPluginTests.cs b/tests/Avalonia.Markup.UnitTests/Data/Plugins/ExceptionValidationPluginTests.cs
index 4a34791008..7b7128ed2f 100644
--- a/tests/Avalonia.Markup.UnitTests/Data/Plugins/ExceptionValidationPluginTests.cs
+++ b/tests/Avalonia.Markup.UnitTests/Data/Plugins/ExceptionValidationPluginTests.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Markup.UnitTests.Data.Plugins
public class ExceptionValidationPluginTests
{
[Fact]
- public void Produces_BindingNotifications()
+ public void Produces_Correct_Results()
{
var inpcAccessorPlugin = new InpcPropertyAccessorPlugin();
var validatorPlugin = new ExceptionValidationPlugin();
@@ -28,12 +28,12 @@ namespace Avalonia.Markup.UnitTests.Data.Plugins
validator.SetValue(-2, BindingPriority.LocalValue);
validator.SetValue(6, BindingPriority.LocalValue);
- Assert.Equal(new[]
+ Assert.Equal(new object[]
{
- new BindingNotification(0),
- new BindingNotification(5),
+ 0,
+ 5,
new BindingNotification(new ArgumentOutOfRangeException("value"), BindingErrorType.DataValidationError),
- new BindingNotification(6),
+ 6,
}, result);
}
diff --git a/tests/Avalonia.Markup.UnitTests/Data/Plugins/IndeiValidationPluginTests.cs b/tests/Avalonia.Markup.UnitTests/Data/Plugins/IndeiValidationPluginTests.cs
index 788bc25a34..9e6657e0a1 100644
--- a/tests/Avalonia.Markup.UnitTests/Data/Plugins/IndeiValidationPluginTests.cs
+++ b/tests/Avalonia.Markup.UnitTests/Data/Plugins/IndeiValidationPluginTests.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Markup.UnitTests.Data.Plugins
public class IndeiValidationPluginTests
{
[Fact]
- public void Produces_BindingNotifications()
+ public void Produces_Correct_Results()
{
var inpcAccessorPlugin = new InpcPropertyAccessorPlugin();
var validatorPlugin = new IndeiValidationPlugin();
@@ -29,19 +29,19 @@ namespace Avalonia.Markup.UnitTests.Data.Plugins
data.Maximum = 10;
data.Maximum = 5;
- Assert.Equal(new[]
+ Assert.Equal(new object[]
{
- new BindingNotification(0),
- new BindingNotification(5),
+ 0,
+ 5,
// Value is first signalled without an error as validation hasn't been updated.
- new BindingNotification(6),
+ 6,
// Then the ErrorsChanged event is fired.
new BindingNotification(new Exception("Must be less than Maximum"), BindingErrorType.DataValidationError, 6),
// Maximum is changed to 10 so value is now valid.
- new BindingNotification(6),
+ 6,
// And Maximum is changed back to 5.
new BindingNotification(new Exception("Must be less than Maximum"), BindingErrorType.DataValidationError, 6),
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Validation.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Validation.cs
index 8759cb42c5..fd15d97fbf 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Validation.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Validation.cs
@@ -45,10 +45,10 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data
Assert.Equal(
new[]
{
- new BindingNotification(5),
- new BindingNotification(6),
+ null, // 5
+ null, // 6
new BindingNotification(new ArgumentOutOfRangeException("value"), BindingErrorType.DataValidationError),
- new BindingNotification(7),
+ null, // 7
},
target.Notifications.AsEnumerable());
}
@@ -94,7 +94,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data
public IList Notifications { get; } = new List();
- protected override void BindingNotificationReceived(AvaloniaProperty property, BindingNotification notification)
+ protected override void UpdateDataValidation(AvaloniaProperty property, BindingNotification notification)
{
Notifications.Add(notification);
}