Proper MVVM ViewModel and Model pattern

1.2k views Asked by At

I haven't found an exact answer to this. Some people have mentioned that binding directly to the model as inappropriate for MVVM, however I'm trying to decide if the following pattern still follows MVVM:

View:

<TextBox Text="{Binding InfoForProcessing.BatchId}"/> <TextBox Text="{Binding InfoForProcessing.BatchStatus}"/>

ViewModel:

private ProcessingTaskModel _infoForProcessing;
public ProcessingTaskModel InfoForProcessing
{
    get
    {
        return _infoForProcessing;
    }
    private set
    {
        _infoForProcessing = value;
        RaisePropertyChanged();
    }
}
....
//doing some processing...then tell Model to populate the data:
InfoForProcessing.ResolveBatchInfo(...);

Model: (Implements INotifyPropertyChanged)

private string _batchId;
public string BatchId   //VIEWABLE
{
    get
    {
        return _batchId;
    }
    private set
    {
        _batchId = value;
        RaisePropertyChanged();
    }
}

private string _batchStatus;
public string BatchStatus  //VIEWABLE
{
    get
    {
        return _batchStatus;
    }
    private set
    {
        _batchStatus = value;
        RaisePropertyChanged();
    }
}

public bool ResolveBatchInfo(...){
    //Get data from Database...
    ...
    //Now Populate Properties with retrieved data (or return false on error)
    BatchId = dr[0].ToString();
    BatchStatus = dr[1].ToString();
    return true;
}

I see another way to do this. I can copy those properties to the ViewModel, bind to them, and have the ViewModel populate them when returned by the Model.

For my current project here, some of the data in the Model is a dependency of queries that will be performed later

I've also made sure to encapsulate as much as possible, and only expose the properties that the View and ViewModel needs to see, while restricting setters as well.

4

There are 4 answers

8
BradleyDotNET On BEST ANSWER

Your design, as is, is non-conforming in my opinion, as your data object contains model logic (the ResolveBatchInfo method). Here are two potential solutions:

  1. Have seperate View Model and Model objects. In this scenario, each has their own methods. INPC for the View Model classes and database methods in the Model classes. (as shown here)

  2. Have your POCOs "float" between layers. The important part here is that besides INPC, there is no logic in the objects, they are just data. Under this design, you would have a separate model class that encapsulates data operations and would have a method that returned populated BatchInfo objects.

I usually do (2) in my own projects, as it provides for better seperation of concerns and limits code/data replication.

Of course, with any of the three approaches (my two plus yours) the most important factor is writing code that makes sense not that it is "pure" MVVM. So go with the design that will make your life the easiest down the road.

0
ΩmegaMan On

Best to list this as bullets

  1. Model DTOs can adhere to INotifyPropertyChange and be binding targets.
  2. The VM should handle any database calls which are initiated from the View and populate stored data on the VM.

I prefer to keep my Models as POCO type entities and not the operation to get the models.

What you describe as your Model is really attributes/properties of a database operation; its status.


Short Answer

All of those items on your model should be moved and done on your VM and bound accordingly.

0
User92 On

Personally I don't mind either way, but many people (including the company who I currently work for) believe that wrapping the properties of the model, in the viewmodel is a more 'pure' approach. For me personally though, I think that it's important to think of MVVM as a guide of good practice, rather than a set of rules to be followed absolutely. I've come across instances before where I've been told to forget wrapping the properties of the model, simply because it needed to get done quickly.

1
James Harcourt On

One common stream of thinking is that - for some reason - you cannot bind directly to Model properties in your Views.

However, given that the objective of MVVM is to abstract the UI/View away from the logic, this will not be broken by bindings of this form:

{Binding ViewModel.Model.Property}

This also means you are not copying properties from Model to ViewModel all the time.