Clear data validation when binding completes.

This commit is contained in:
Steven Kirk
2023-02-21 11:42:45 +01:00
parent a899185afb
commit 40ab20146f
5 changed files with 90 additions and 3 deletions
@@ -9,11 +9,13 @@ namespace Avalonia.PropertyStore
IDisposable
{
private readonly ValueStore _owner;
private readonly bool _hasDataValidation;
private IDisposable? _subscription;
public DirectBindingObserver(ValueStore owner, DirectPropertyBase<T> property)
{
_owner = owner;
_hasDataValidation = property.GetMetadata(owner.Owner.GetType())?.EnableDataValidation ?? false;
Property = property;
}
@@ -33,10 +35,17 @@ namespace Avalonia.PropertyStore
{
_subscription?.Dispose();
_subscription = null;
_owner.OnLocalValueBindingCompleted(Property, this);
OnCompleted();
}
public void OnCompleted()
{
_owner.OnLocalValueBindingCompleted(Property, this);
if (_hasDataValidation)
_owner.Owner.OnUpdateDataValidation(Property, BindingValueType.UnsetValue, null);
}
public void OnCompleted() => _owner.OnLocalValueBindingCompleted(Property, this);
public void OnError(Exception error) => OnCompleted();
public void OnNext(T value)
@@ -10,11 +10,13 @@ namespace Avalonia.PropertyStore
IDisposable
{
private readonly ValueStore _owner;
private readonly bool _hasDataValidation;
private IDisposable? _subscription;
public DirectUntypedBindingObserver(ValueStore owner, DirectPropertyBase<T> property)
{
_owner = owner;
_hasDataValidation = property.GetMetadata(owner.Owner.GetType())?.EnableDataValidation ?? false;
Property = property;
}
@@ -30,6 +32,9 @@ namespace Avalonia.PropertyStore
_subscription?.Dispose();
_subscription = null;
_owner.OnLocalValueBindingCompleted(Property, this);
if (_hasDataValidation)
_owner.Owner.OnUpdateDataValidation(Property, BindingValueType.UnsetValue, null);
}
public void OnCompleted() => _owner.OnLocalValueBindingCompleted(Property, this);
@@ -37,10 +37,17 @@ namespace Avalonia.PropertyStore
{
_subscription?.Dispose();
_subscription = null;
OnCompleted();
}
public void OnCompleted()
{
if (_hasDataValidation)
_owner.Owner.OnUpdateDataValidation(Property, BindingValueType.UnsetValue, null);
_owner.OnLocalValueBindingCompleted(Property, this);
}
public void OnCompleted() => _owner.OnLocalValueBindingCompleted(Property, this);
public void OnError(Exception error) => OnCompleted();
public void OnNext(T value)
@@ -92,6 +92,48 @@ namespace Avalonia.Base.UnitTests
Assert.Equal(1, target.Notifications.Count);
}
[Fact]
public void Disposing_Binding_Subscription_Clears_DataValidation()
{
var target = new Class1();
var source = new Subject<BindingValue<int>>();
var property = GetProperty();
var error = new Exception();
var sub = target.Bind(property, source);
source.OnNext(6);
source.OnNext(BindingValue<int>.DataValidationError(error));
sub.Dispose();
Assert.Equal(new Notification[]
{
new(BindingValueType.Value, 6, null),
new(BindingValueType.DataValidationError, 6, error),
new(BindingValueType.UnsetValue, 6, null),
}, target.Notifications);
}
[Fact]
public void Completing_Binding_Clears_DataValidation()
{
var target = new Class1();
var source = new Subject<BindingValue<int>>();
var property = GetProperty();
var error = new Exception();
target.Bind(property, source);
source.OnNext(6);
source.OnNext(BindingValue<int>.DataValidationError(error));
source.OnCompleted();
Assert.Equal(new Notification[]
{
new(BindingValueType.Value, 6, null),
new(BindingValueType.DataValidationError, 6, error),
new(BindingValueType.UnsetValue, 6, null),
}, target.Notifications);
}
protected abstract T GetProperty();
protected abstract T GetNonValidatedProperty();
}
@@ -67,6 +67,30 @@ namespace Avalonia.Markup.UnitTests.Data
Assert.Null(target.DataValidationError);
}
[Fact]
public void Disposing_Binding_Subscription_Clears_DataValidation()
{
var (target, property) = CreateTarget();
var binding = new Binding(nameof(ExceptionValidatingModel.Value))
{
Mode = BindingMode.TwoWay
};
target.DataContext = new IndeiValidatingModel
{
Value = 200,
};
var sub = target.Bind(property, binding);
Assert.Equal(200, target.GetValue(property));
Assert.IsType<DataValidationException>(target.DataValidationError);
sub.Dispose();
Assert.Null(target.DataValidationError);
}
private protected abstract (DataValidationTestControl, T) CreateTarget();
}