MVVM - Validating the model when a field in the viewmodel is changed

477 views Asked by At

I'm using the MVVMLight libraries with a Database-First EF model. I can't quite figure out how to validate the model when a certain field in my viewmodel has changed. This works fine when I'm updating individual Properties of the model as I have a call to Validate in the set methods. I'm not sure how this works elsewhere.

For the sake of example, I have a Person class (model) in my application has a property called Name implemented like so in the view model:

private Person _currentPerson; 

// Code omitted...

[Required(ErrorMessage = "Name is a required field.")]
public string Name
{
    get { return _currentPerson.Name; }
    set
    {
        if (value != _currentPerson.Name)
        {
            _currentPerson.Name = value;
            RaisePropertyChanged();
            Validate(_currentPerson.Name);
        }
    }
}

When I want to create a new person, I have a method attached to a RelayCommand called NewPerson with this code:

public RelayCommand NewCommand { get { return _newCommand ?? (_newCommand = new RelayCommand(NewPerson)); } }

// Code omitted...

private void NewPerson()
{
    _currentPerson = new Person();
    RaisePropertyChanged(String.Empty); // Updates model and UI.
}

How do I now validate _currentPerson without calling Validate on every single property? Because this model class has quite a few properties... (30+).

The only thing I've tried is using reflection to iterate through all the properties of the Person object, but this kept causing exceptions which I didn't really understand.

Update: Managed to get something working, but there has to be a better way of doing this:

private void NewPerson()
{
    _currentPerson = new Person();
    RaisePropertyChanged(String.Empty); // Updates model and UI.
    ValidatePerson(_currentPerson);
}

private void ValidatePerson(Person p)
{
    Validate(p.Forename, "Forename");
    Validate(p.Surname, "Surname");
    Validate(p.DateOfBirth, "DateOfBirth");
    // There's about another 30 calls to Validate here...
}
2

There are 2 answers

2
Sascha Minor On BEST ANSWER

How about validating the whole person object in your Validate() methode, not just a single property?

2
kidshaw On

If you want separate validation logic by property, just add a separate validate all method for when the whole model needs checking. That can call your individual methods or perform something more bespoke.