I am getting started with using ValidationRules in my WPF application, but quite confused.
I have the following simple rule:
class RequiredRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
if (String.IsNullOrWhiteSpace(value as string))
{
return new ValidationResult(false, "Must not be empty");
}
else
{
return new ValidationResult(true, null);
}
}
}
Used in XAML as follows:
<TextBox>
<TextBox.Text>
<Binding Path="Identity.Name">
<Binding.ValidationRules>
<validation:RequiredRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
This mostly works as I would expect. I was surprised to see that my source property (Identity.Name
) was not being set; I have an undo function that never sees the change, and there is no way to revert the value other than re-type it (not good).
Microsoft's Data Binding Overview describes the validation process near the bottom, which explains this behavior very well. Based on this, I would want to have my ValidationStep
set to UpdatedValue
.
<validation:RequiredRule ValidationStep="UpdatedValue"/>
This is where things get weird for me. Instead of Validate() being called with object value being the property value that was set (i.e., a string), I get a System.Windows.Data.BindingExpression
! I don't see anything in Microsoft's documentation that describes this behavior.
In the debugger, I can see the source object (the DataContext
of the TextBox
), navigate the path to the property, and see that the value has been set. However, I don't see any good way to get to the right property within the validation rule.
Note: With ValidationStep
as ConvertedProposedValue
, I get the entered string (I don't have a converter in use), but it also blocks the source property update when validation fails, as expected. With CommittedValue
, I get the BindingExpression
instead of the string.
There are several questions in here:
Why do I get an inconsistent argument type being passed to Validate() based on the ValidationStep setting?
How can I get to the actual value from the BindingExpression?
Alternately, is there a good way to allow the user to revert the TextBox to the previous (valid) state? (As I mentioned, my own undo function never sees the change.)