diff --git a/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs index 2e83e0c25e..7abbcab245 100644 --- a/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs @@ -85,8 +85,9 @@ namespace Avalonia.Data.Core.Plugins if (target != null) { var errors = target.GetErrors(_name)? - .Cast() - .Where(x => x != null).ToList(); + .Cast() + .Where(x => x != null) + .ToList(); if (errors?.Count > 0) { @@ -100,16 +101,16 @@ namespace Avalonia.Data.Core.Plugins return new BindingNotification(value); } - private Exception GenerateException(IList errors) + private Exception GenerateException(IList errors) { if (errors.Count == 1) { - return new Exception(errors[0]); + return new DataValidationException(errors[0]); } else { return new AggregateException( - errors.Select(x => new Exception(x))); + errors.Select(x => new DataValidationException(x))); } } } diff --git a/src/Avalonia.Base/Data/DataValidationException.cs b/src/Avalonia.Base/Data/DataValidationException.cs new file mode 100644 index 0000000000..e38e6c30ad --- /dev/null +++ b/src/Avalonia.Base/Data/DataValidationException.cs @@ -0,0 +1,21 @@ +using System; + +namespace Avalonia.Data +{ + /// + /// Exception, which wrap validation errors. + /// + public class DataValidationException : Exception + { + /// + /// Initializes a new instance of the class. + /// + /// Data of validation error. + public DataValidationException(object errorData) : base(errorData?.ToString()) + { + ErrorData = errorData; + } + + public object ErrorData { get; } + } +} diff --git a/src/Avalonia.Controls/DataValidationErrors.cs b/src/Avalonia.Controls/DataValidationErrors.cs index f0d7f8257e..50b387e636 100644 --- a/src/Avalonia.Controls/DataValidationErrors.cs +++ b/src/Avalonia.Controls/DataValidationErrors.cs @@ -22,8 +22,8 @@ namespace Avalonia.Controls /// /// Defines the DataValidationErrors.Errors attached property. /// - public static readonly AttachedProperty> ErrorsProperty = - AvaloniaProperty.RegisterAttached>("Errors"); + public static readonly AttachedProperty> ErrorsProperty = + AvaloniaProperty.RegisterAttached>("Errors"); /// /// Defines the DataValidationErrors.HasErrors attached property. @@ -76,7 +76,7 @@ namespace Avalonia.Controls private static void ErrorsChanged(AvaloniaPropertyChangedEventArgs e) { var control = (Control)e.Sender; - var errors = (IEnumerable)e.NewValue; + var errors = (IEnumerable)e.NewValue; var hasErrors = false; if (errors != null && errors.Any()) @@ -91,11 +91,11 @@ namespace Avalonia.Controls classes.Set(":error", (bool)e.NewValue); } - public static IEnumerable GetErrors(Control control) + public static IEnumerable GetErrors(Control control) { return control.GetValue(ErrorsProperty); } - public static void SetErrors(Control control, IEnumerable errors) + public static void SetErrors(Control control, IEnumerable errors) { control.SetValue(ErrorsProperty, errors); } @@ -112,14 +112,14 @@ namespace Avalonia.Controls return control.GetValue(HasErrorsProperty); } - private static IEnumerable UnpackException(Exception exception) + private static IEnumerable UnpackException(Exception exception) { if (exception != null) { var aggregate = exception as AggregateException; var exceptions = aggregate == null ? - (IEnumerable)new[] { exception } : - aggregate.InnerExceptions; + new[] { GetExceptionData(exception) } : + aggregate.InnerExceptions.Select(GetExceptionData).ToArray(); var filtered = exceptions.Where(x => !(x is BindingChainException)).ToList(); if (filtered.Count > 0) @@ -130,5 +130,13 @@ namespace Avalonia.Controls return null; } + + private static object GetExceptionData(Exception exception) + { + if (exception is DataValidationException dataValidationException) + return dataValidationException.ErrorData; + + return exception; + } } }