I have a TextBox
, and I am using ValidationRule
.
<TextBox ..>
<TextBox.Text>
<Binding
Mode="TwoWay"
Path="DataTextBox"
UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<validations:TextBoxValidation />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Here is the validation rule:
public class TextBoxValidation: ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
return (string.IsNullOrEmpty(value as string)) ?
new ValidationResult(false, "This textbox cannot be empty") :
new ValidationResult(true, null);
}
}
I have this property in my ViewModel
:
private string? _DataTextBox = string.Empty; //by default, set it as empty.
public string? DataTextBox
{
get => _DataTextBox;
set { SetProperty(ref _DataTextBox, value); }
}
I noticed that when I type in my TextBox
, e.g. ABCDEFG
, and then delete all the text, the DataTextBox
property in my view model bound to the Text
property of my TextBox
still has the value A
.
This behavior appears only when using the ValidationRule
.
Why is that and how to fix it?
CodePudding user response:
For validation rules, you can specify when they are applied via the ValidationStep
property. The default value is RawProposedValue
which means:
Runs the
ValidationRule
before any conversion occurs.
This also means that the validation occurs before the value of the bound source property is updated. Consequently, if the validation rule fails, e.g. the text box is left empty, the value will not be transferred back, since it is invalid, resulting in the last valid value for the DataTextBox
property not being overwritten (in your case a
).
You can change this behavior by specifying a different validation step after updating the source:
-
Runs the ValidationRule after the source is updated.
-
Runs the ValidationRule after the value has been committed to the source.
Then the value is updated before the validation rule is checked.
<local:TextBoxValidation ValidationStep="UpdatedValue" />
<local:TextBoxValidation ValidationStep="CommittedValue" />