How to implement validation before setting a property value in MVVM (WPF)

mvvmnetwpf

Scenario.

  • ViewModel has a property State.
  • View has a ComboBox that allows to change value of State.
  • ViewModel needs to run some validation (call bool ValidateState(State value) method) before setting value of State property.

Question.

How would you implement it?

My concerns.

  • I want my solution to be generic so I could use it in different similar scenarios. For example in scenario where ValidateState() is an async method.
  • I do not want change value of State in ViewModel unless I 100% sure it's valid.
  • If new value of State is not accepted (is not valid) I want ComboBox to keep having the old value as selected.

Disclaimer. I know there are multiple ways of implementing it. Also I'm not a MVVM novice. I would like to discuss which solution you think better suits this scenario and possibly discuss pros and cons of it.

Best Answer

You could implement INotifyPropertyChanged interface and use the setters to perform the validations. After validation succeeds, you set the private field and notify the changed property for the UI to be updated according to ViewModel's State.

Here goes some code as example.

class YourViewModel : INotifyPropertyChanged {
    private State _state;

    public event PropertyChangedEventHandler PropertyChanged;

    public State State {
        public get { return _state; }
        public set {
            ValidateState(value);
            //If async operation is required, you could set
            //this ViewModel state to "Validating" or something like that
        }
    }

    //ValidateState
    void ValidateState(State newState) {
        //Perform validations
        if (validEnough) {
            //Change the actual state, and also the UI state
            _state = newState;

            //Tells ui to update its view
            PropertyChanged(this, new PropertyChangedEventArgs("State"));
        }
    }

}

//Example of unit test
[TestMethod]
public void SetState_HasNoPermissions_DoesNotChangeState() {
    //... setup resources for the test
    yourViewModel.State = State.FirstStep;

    Assert.NotEquals(yourViewModel.State, State.FirstStep);
}

Update to address some comments

... I personally think ViewModel should only contain logic, but should not know anything about View

That's correct. The important stuff of your screen is the State, not the combobox (which is not known by the viewModel). I can't see how my example fails this.

Examples: ... it's not OK to generate readable text for View like error meessages ...

Who said it is no ok to do that? Do you see any problem in having a viewModel loading localized messages at runtime, for example? If it's OK or not will depend on your application needs.

So the thing I'm trying to say is I do not agree with this: here your viewModel IS the user interface.

What I tried to say is that graphics and visual stuff are placed ONLY in the View, and the state and behaviour are placed in the ViewModel. So, therefore, you GUIs are represented partly by the View, and partly by the ViewModel. That's why I said that in the example, the viewModel is your user interface, since i'm not considering details such as Combobox or GridView or whatever; I'm only interested in the behaviour of the screen, and this behavior should be entirely implemented in your viewModel, if you chose to follow MVVM pattern.

But, you don't need to believe me, please just read Presentation Model (another name for the same pattern) article and the other source mentioned below.

Also it's not view that requires validation - bussinss logic ruquires it. And therefore it should implemented in the ViewModel layer rather then in View layer.

What I meant is that there might be a requirement like: "When user changes the value of the state, there must be performed a validation on it, and the view must update this value only if validation succeeds."

Because of that, you want to implement some behavior on you GUI: the user changes a combobox' value, and the validation occurs; if validation fails, combobox's value stays the same; otherwise a new value is set in the combobox.

The above statement is implemented by my example, following ModelView-ViewModel design pattern. Actually, in the code example I put ValidateState in the ViewModel, but the idea is that the viewModel triggers the validation logic that should be implemented somewhere else; the code is to serve just as an example to aid you in your development scenario. But, if anything above seems like bad practice after all to you, this is just a suggestion anyways :)

Programming best practices are same for everything. If you use MVVM architecture pattern it doesn't mean you should be allowed introducing code smells.

I agree and I personally don't see the code smell here.

One last thing. If your viewModel IS the user interface then how is it different from code behind file? ... What is the actual benefit of separating ViewModel from View if ViewModel "serves" View?

Let me answer that by quoting Martin Fowler in his Presentation Model article:

Presentation Model: Represent the state and behavior of the presentation independently of the GUI controls used in the interface

...And by quoting MVVM article from Msdn:

It provides separation of concerns. ... A clean separation between application logic and the UI will make an application easier to test, maintain, and evolve. It improves code re-use opportunities and enables the developer-designer workflow.

About the code-behind file: this is just the C# part of your XAML. All code you put there should address only presentation concerns; ideally, behavior and state of your GUI should be implemented in the ViewModel classes. At least this is what is described as the pattern, by the sources below. I suggest you to fully read and understand below articles.

Sources:

https://martinfowler.com/eaaDev/PresentationModel.html

https://msdn.microsoft.com/en-us/library/hh848246.aspx

Related Topic