totoro
totoro

Reputation: 3407

WPF why isn't error message shown?

I want to validate some Text in a TextBlock

TextBlock xaml:

<TextBlock x:Name="numInput" Validation.ErrorTemplate="{StaticResource errorTemplate}" >
    <TextBlock.Text>
        <Binding Path="Text" RelativeSource="{RelativeSource self}" NotifyOnValidationError="True">
            <Binding.ValidationRules>
                <local: NumberValidator />
            </Binding.ValidationRules>
        </Binding>
    </TextBlock.Text>
</TextBlock>

The Text is added in codebehind by some button clicks in the GUI (i.e. a touch screen)

errorTemplate

<ControlTemplate x:Key="errorTemplate">
    <StackPanel>
        <TextBlock Foreground="Red">error msg</TextBlock>
        <AdornedElementPlaceholder/>
    </StackPanel>
</ControlTemplate>

NumberValidator

class NumberValidator : ValidationRule {
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) {
        Console.WriteLine("validating numbers!!");
        int num = -1;
        try {
            num = Int32.Parse(value.ToString());
        }
        catch (Exception e) {
            return new ValidationResult(false, "input must be numbers!");
        }

        if (num > 999 || num < 1) {
            return new ValidationResult(false, string.Format("must be integers from {0} to {1}", 1, 999));
        }
        return new ValidationResult(true, null);
    }
}

Questions:

  1. No error message is shown. In fact, NumberValidator isn't even called. Why?

  2. How to validate the error only when a Button is clicked?

  3. How to pass valid range (i.e min, max) information to the NumberValidator?

Thanks!

Upvotes: 0

Views: 96

Answers (1)

Grx70
Grx70

Reputation: 10349

I assume that you want to perform validation in source-to-target direction (provide visual feedback for model errors), therefore my answer only applies if this is the case.

  1. Validation rules are by design only checked in target-to-source direction (the main idea here is to validate user input), so when you change the value on the model, validation rules are not checked. In order to perform validation in source-to-target direction, your model should implement either IDataErrorInfo or INotifyDataErrorInfo (the latter being supported only in .NET 4.5 or newer), and ValidatesOnDataErrors should be set to true on the binding.

  2. The validation occurs whenever binding is updated, so if the button click updates the property on the model (or, more specifically, raises PropertyChanged event), the validation will be performed. Note that if property is changed on some other occasion, the validation will also be performed, so in order to perform the validation only on button click make sure the property is changed (or PropertyChanged is raised) only then.

  3. Despite using ValidationRule derivatives is not appropriate approach in assumed scenario, the answer is to define Max and Min properties on the NumberValidator class, and then use them in XAML like so: <local:NumberValidator Min="0" Max="100"/>.

For more information on bindings see Data Binding Overview.

Upvotes: 2

Related Questions