Question

The idea is, I want to show a single error at the bottom of the window, but the source of an error can be several elements like TextBoxes.

I have succesfully created a validation of a single field, yet i struggle to achieve my new goal.

Based on internet tutorials, i have created ValidationRule which only checks if a entered text is empty. Then added ErrorConverter:IValueConverter which translates the error to string. On the XAML part i have a validation rule bound to 2 TextBoxes

<TextBox.Text>
    <Binding ElementName="Self" Path="MyProperty" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
        <Binding.ValidationRules>
            <local:ValidateEmpty />
        </Binding.ValidationRules>
    </Binding>
</TextBox.Text>

and one TextBox for displaying error

Text="{Binding ElementName=myElement,
      Path=(Validation.Errors).CurrentItem,
      Converter={StaticResource ErrorConverter}

I have all the needed DependencyProperties. The problem is, error textbox can only be bound to one component at a time (myElement in my example), if i change the ElementName to my grid name or anything else, nothing happens, no error message is shown.

So what should i do be able to "capture" errors from multiple components?

Était-ce utile?

La solution

I would suggest two different ways of doing that:

1st way: ViewModel-side validation

If your ViewModel implements IDataErrorInfo to define errors in the inputs, then you must have a string Error in your class. This string is actually here for the exact thing you're looking to do: Having a single justification for multiple errors.

Here is my way of implementing it:

    public string Error
    {
        get { return PerformValidation(string.Empty); }
    }

    public virtual string this[string propertyName]
    {
        get
        {
            return PerformValidation(propertyName);
        }
    }

My PerformValidation method is virtual, to be overridden in the inheriting classes. But here is what it would look like:

    protected override void PerformValidation(string propertyName = null)
    {

        if (string.IsNullOrEmpty(propertyName) || propertyName == "Property1")
        { }
        else if (string.IsNullOrEmpty(propertyName) || propertyName == "Property2")
        { }
        //...
    }

Then, my TextBlock is simply bound to the Error string which would always show the first encountered error

2nd way: UI-ValidationRule side

Alternatively, you can simply use a MultiBinding, or simply a TextBlock containing Run objects. Simple example:

        <TextBlock TextAlignment="Center">
             <Run Text="{Binding ElementName=myElement,
                         Path=(Validation.Errors).CurrentItem,
                         Converter={StaticResource ErrorConverter}}" />
             <Run Text="{Binding ElementName=myElement2,
                         Path=(Validation.Errors).CurrentItem,
                         Converter={StaticResource ErrorConverter}}" />
             <Run Text="{Binding ElementName=myElement3,
                         Path=(Validation.Errors).CurrentItem,
                         Converter={StaticResource ErrorConverter}}" />
        </TextBlock>

And just add one Run per Element

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top