Browse Source

Fix TextBox validation error persisting when reverting to same valid value (#20780)

* Fix TextBox validation error persisting when reverting to same valid value

When a TwoWay binding with validation had an error and the user set the
target back to the same value that was last successfully written to the
source, WriteTargetValueToSource() would bail out early because the
target value matched LeafNode.Value. This prevented WriteValueToSource()
from being called, so the validation error was never cleared.

Add an ErrorType check to the condition in WriteTargetValueToSource() so
that the write-through still happens when there is a pending validation
error, matching the pattern already used in WriteValueToSource() at
line 310.

Fixes #20534

https://claude.ai/code/session_01LTinLuE1bsNKaLPuDSNuuw

* Add test for validation error clearing when reverting to same valid value

Reproduces the scenario from #20534 where a TwoWay binding with a
setter that throws on invalid values fails to clear the validation error
when the target is set back to the same value that was last successfully
written to the source.

https://claude.ai/code/session_01LTinLuE1bsNKaLPuDSNuuw

* Remove redundant checks in WriteTargetValueToSource()
release/11.3.13
Evan 7 months ago
committed by Julien Lebosquain
parent
commit
98c9211cfa
  1. 7
      src/Avalonia.Base/Data/Core/BindingExpression.cs
  2. 36
      tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.DataValidation.cs

7
src/Avalonia.Base/Data/Core/BindingExpression.cs

@ -510,12 +510,9 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
StopDelayTimer(); StopDelayTimer();
if (TryGetTarget(out var target) && if (TryGetTarget(out var target) &&
TargetProperty is not null && TargetProperty is not null)
target.GetValue(TargetProperty) is var value &&
LeafNode is { } leafNode &&
!TypeUtilities.IdentityEquals(value, leafNode.Value, TargetType))
{ {
WriteValueToSource(value); WriteValueToSource(target.GetValue(TargetProperty));
} }
} }

36
tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.DataValidation.cs

@ -133,6 +133,42 @@ public partial class BindingExpressionTests
GC.KeepAlive(data); GC.KeepAlive(data);
} }
[Fact]
public void Setter_Exception_Error_Is_Cleared_When_Reverting_To_Same_Valid_Value()
{
// Issue #20534: When a setter throws on an invalid value and the user
// reverts to the same valid value that was last successfully set, the
// validation error should be cleared.
var data = new ExceptionViewModel { MustBePositive = 5 };
var target = CreateTargetWithSource(
data,
o => o.MustBePositive,
enableDataValidation: true,
mode: BindingMode.TwoWay);
// Step 1: Set a valid value.
target.Int = 10;
Assert.Equal(10, data.MustBePositive);
AssertNoError(target, TargetClass.IntProperty);
// Step 2: Set an invalid value — setter throws, error appears.
target.Int = -5;
Assert.Equal(10, data.MustBePositive);
AssertBindingError(
target,
TargetClass.IntProperty,
new ArgumentOutOfRangeException("value"),
BindingErrorType.DataValidationError);
// Step 3: Revert to the same valid value (10). The error must clear.
target.Int = 10;
Assert.Equal(10, data.MustBePositive);
AssertNoError(target, TargetClass.IntProperty);
GC.KeepAlive(data);
}
[Fact] [Fact]
public void Indei_Validation_Does_Not_Subscribe_When_DataValidation_Not_Enabled() public void Indei_Validation_Does_Not_Subscribe_When_DataValidation_Not_Enabled()
{ {

Loading…
Cancel
Save