Browse Source
This will replace BindingError and IValidationStatus for bindings that want to notify binding/validation errors. Still WIP.pull/691/head
committed by
Steven Kirk
21 changed files with 266 additions and 136 deletions
@ -1,59 +0,0 @@ |
|||||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|
||||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|
||||
|
|
||||
using System; |
|
||||
|
|
||||
namespace Avalonia.Data |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Represents a recoverable binding error.
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// When produced by a binding source observable, informs the binding system that an error
|
|
||||
/// occurred. It can also provide an optional fallback value to be pushed to the binding
|
|
||||
/// target.
|
|
||||
///
|
|
||||
/// Instead of using <see cref="BindingError"/>, one could simply not push a value (in the
|
|
||||
/// case of a no fallback value) or push a fallback value, but BindingError also causes an
|
|
||||
/// error to be logged with the correct binding target.
|
|
||||
/// </remarks>
|
|
||||
public class BindingError |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="BindingError"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="exception">An exception describing the binding error.</param>
|
|
||||
public BindingError(Exception exception) |
|
||||
{ |
|
||||
Exception = exception; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="BindingError"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="exception">An exception describing the binding error.</param>
|
|
||||
/// <param name="fallbackValue">The fallback value.</param>
|
|
||||
public BindingError(Exception exception, object fallbackValue) |
|
||||
{ |
|
||||
Exception = exception; |
|
||||
FallbackValue = fallbackValue; |
|
||||
UseFallbackValue = true; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets the exception describing the binding error.
|
|
||||
/// </summary>
|
|
||||
public Exception Exception { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Get the fallback value.
|
|
||||
/// </summary>
|
|
||||
public object FallbackValue { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Get a value indicating whether the fallback value should be pushed to the binding
|
|
||||
/// target.
|
|
||||
/// </summary>
|
|
||||
public bool UseFallbackValue { get; } |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,169 @@ |
|||||
|
// Copyright (c) The Avalonia Project. All rights reserved.
|
||||
|
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
||||
|
|
||||
|
using System; |
||||
|
|
||||
|
namespace Avalonia.Data |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines the types of binding errors for a <see cref="BindingNotification"/>.
|
||||
|
/// </summary>
|
||||
|
public enum BindingErrorType |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// There was no error.
|
||||
|
/// </summary>
|
||||
|
None, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// There was a binding error.
|
||||
|
/// </summary>
|
||||
|
Error, |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// There was a data validation error.
|
||||
|
/// </summary>
|
||||
|
DataValidationError, |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Represents a binding notification that can be a valid binding value, or a binding or
|
||||
|
/// data validation error.
|
||||
|
/// </summary>
|
||||
|
public class BindingNotification : IValidationStatus |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A binding notification representing the null value.
|
||||
|
/// </summary>
|
||||
|
public static readonly BindingNotification Null = |
||||
|
new BindingNotification(null); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A binding notification representing <see cref="AvaloniaProperty.UnsetValue"/>.
|
||||
|
/// </summary>
|
||||
|
public static readonly BindingNotification UnsetValue = |
||||
|
new BindingNotification(AvaloniaProperty.UnsetValue); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="BindingNotification"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="value">The binding value.</param>
|
||||
|
public BindingNotification(object value) |
||||
|
{ |
||||
|
Value = value; |
||||
|
HasValue = true; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="BindingNotification"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="error">The binding error.</param>
|
||||
|
/// <param name="errorType">The type of the binding error.</param>
|
||||
|
public BindingNotification(Exception error, BindingErrorType errorType) |
||||
|
{ |
||||
|
if (errorType == BindingErrorType.None) |
||||
|
{ |
||||
|
throw new ArgumentException($"'errorType' may not be None"); |
||||
|
} |
||||
|
|
||||
|
Error = error; |
||||
|
ErrorType = errorType; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="BindingNotification"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="error">The binding error.</param>
|
||||
|
/// <param name="errorType">The type of the binding error.</param>
|
||||
|
/// <param name="fallbackValue">The fallback value.</param>
|
||||
|
public BindingNotification(Exception error, BindingErrorType errorType, object fallbackValue) |
||||
|
: this(error) |
||||
|
{ |
||||
|
Value = fallbackValue; |
||||
|
HasValue = true; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value that should be passed to the target when <see cref="HasValue"/>
|
||||
|
/// is true.
|
||||
|
/// </summary>
|
||||
|
public object Value { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value indicating whether <see cref="Value"/> should be pushed to the target.
|
||||
|
/// </summary>
|
||||
|
public bool HasValue { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the error that occurred on the source, if any.
|
||||
|
/// </summary>
|
||||
|
public Exception Error { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the type of error that <see cref="Error"/> represents, if any.
|
||||
|
/// </summary>
|
||||
|
public BindingErrorType ErrorType { get; } |
||||
|
|
||||
|
bool IValidationStatus.IsValid => ErrorType == BindingErrorType.None; |
||||
|
|
||||
|
public static bool operator ==(BindingNotification a, BindingNotification b) |
||||
|
{ |
||||
|
if (object.ReferenceEquals(a, b)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if ((object)a == null || (object)b == null) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return a.HasValue == b.HasValue && |
||||
|
a.ErrorType == b.ErrorType && |
||||
|
(!a.HasValue || object.Equals(a.Value, b.Value)) && |
||||
|
(a.ErrorType == BindingErrorType.None || object.Equals(a.Error, b.Error)); |
||||
|
} |
||||
|
|
||||
|
public static bool operator !=(BindingNotification a, BindingNotification b) |
||||
|
{ |
||||
|
return !(a == b); |
||||
|
} |
||||
|
|
||||
|
public override bool Equals(object obj) |
||||
|
{ |
||||
|
return Equals(obj as BindingNotification); |
||||
|
} |
||||
|
|
||||
|
public bool Equals(BindingNotification other) |
||||
|
{ |
||||
|
return this == other; |
||||
|
} |
||||
|
|
||||
|
public override int GetHashCode() |
||||
|
{ |
||||
|
return base.GetHashCode(); |
||||
|
} |
||||
|
|
||||
|
public BindingNotification WithError(Exception e) |
||||
|
{ |
||||
|
if (e == null) |
||||
|
{ |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
if (Error != null) |
||||
|
{ |
||||
|
e = new AggregateException(Error, e); |
||||
|
} |
||||
|
|
||||
|
if (HasValue) |
||||
|
{ |
||||
|
return new BindingNotification(e, BindingErrorType.Error, Value); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return new BindingNotification(e, BindingErrorType.Error, Value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue