How to implement data validation in MVVM model?

I have an MVVM application that requires data validation. I would like to keep the validation in the model, so the model can be easily used with other view models without having to duplicate validation code. Most examples of data validation using WPF either have validation done on the view model in the MVVM setup, or data validation done on the model when the model is directly linked to the view and the view model is not used.

I would like to have data validation in my model so that the view model will render my model in the view, and I mean that the view can still receive feedback from the model. I am planning on using IDataErrorInfo or Data Annotations for my validation. I have found several examples of this, but neither approach seems ideal.

Done here with data annotations, although it did require a moderate amount of custom code.

I like this IDataErrorInfo approach better since it doesn't include custom code, however I don't know if I'm comfortable with an approach where the entire model is exposed as a single view property and also only exposes the individual properties that are required.

Is there a better or more recommended way to do this?

+3


source to share


2 answers


The data annotation method you linked is somewhat redundant as the framework already has the concept of binding validation rules (see Including Data Binding, Validation, and MVVM in the Next Level ). The only time the data annotation approach is useful is to check in a location completely separate from the user interface.



Apart from these two parameters, using IDataErrorInfo is your only choice. Note that you are not "exposing the entire model to the view as a separate property", rather you are using an interface to expose your custom object to a binding — there is a big difference. If you choose this method, make sure to use resource strings to contain error messages and not use hard text. The IDataErrorInfo method is useful if you have different people working on the view and the viewmodel — the person making the view does not need to know anything about specific view model checks.

+1


source


I ended up avoiding use IDataErrorInfo

as it was a huge pain. We put our validation on the model using attributes.

public class User : ValidatableBase, INotifyPropertyChanged
{
    private string password = string.Empty;

    public event PropertyChangedEventHandler PropertyChanged;

    [ValidateObjectHasValue(
        FailureMessage = "E-Mail can not be left blank.", 
        ValidationMessageType = typeof(ValidationErrorMessage))]
    public string Email
    {
        get
        {
            return this.email;
        }

        set
        {
            this.email = value;
            this.OnPropertyChanged("Email");
        }
    }

    [ValidateStringIsGreaterThan(
        GreaterThanValue = 6, 
        ValidateIfMemberValueIsValid = "Email",  
        FailureMessage = "Password must be greater than 6 characters.", 
        ValidationMessageType = typeof(ValidationErrorMessage))]
    [ValidateStringIsLessThan(
        LessThanValue = 20, 
        ValidateIfMemberValueIsValid = "Email", 
        FailureMessage = "Password must be less than 20 characters.", 
        ValidationMessageType = typeof(ValidationErrorMessage))]
    public string Password
    {
        get
        {
            return this.password;
        }

        set
        {
            this.password = value;
            this.OnPropertyChanged("Password");
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="propertyName"></param>
    protected virtual void OnPropertyChanged(string propertyName = "")
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

      

The above example performs validation to ensure that the email property is not empty, and password validation validates the range. Password validation does not fire until the property Email

is in a valid state.

The validation project is hosted on GitHub and supports a wide range of things.



  • Custom Validation Delegates

  • Intercepting validation results in custom delegates

  • Localized validation error messages
  • INotifyPropertyChanged support
  • Checking all properties in 1 method call
  • Check individual properties if necessary.
  • Validate the request for the entire model or for each property as needed.
  • Input validation from the view model
  • Validation proxy. (Perform validation and pass proxy results).
  • Check based on the result of another property. Nested properties are supported.
  • Conditionally assert based on the state of other properties.
  • Easy templates, so you can get warnings, information and errors.

I've used this on several projects and it works well. The significant benefit I have gained is that I can reuse validation rules for multiple objects (IDataErrorInfo suffers from a lot of copies / attachments) and I can create DataTemplates around which Validation message the rules return. We have templates for warnings and error templates. Gives you a lot of flexibility.

The original goal of the project was to use it for WinRT projects, but it quickly grew to what I use in my mobile and WPF applications.

+2


source







All Articles