views:

1070

answers:

3

There are lots of great examples around on MVVM but I'm still confused.

Lets say you have a CustomerModel and a CustomerViewModel. It seems there would be a Name property on the CustomerModel and one on the CustomerViewModel. The setter on the CustomerViewModel will set the CustomerModel Name property and then call the OnPropertyChanged(PropName) so that the UI will update. Is this really right? Seems like the getter/setters will be defined twice. If you have a model with 50 properties then thats going to get real tedious.

Also, lets say I set a Qty property. The ViewModel updates the Model. The Model updates its Value property based on the new Qty. How does the ViewModel get notified that the Model property changed?

+2  A: 

In the customer example that you give, the CustomerModel contains all the information that is stored by your database (or other backend). The CustomerViewModel contains similar information if it's going to be shown on the UI (Name etc., potentially 50 other properties if you have a large class) but as uses the INotifyPropertyChanged interface to show them as properties that the View (i.e. the XAML) can bind to.

e.g.

public int Name
{
    get
    {
        return this.name;
    }

    set
    {
        if (this.name!= value)
        {
            this.name= value;
            this.OnPropertyChanged("Name");
        }
    }
}

The ViewModel also contains other bits of UI state - Visibility flags, current Tab index, more complex bits of text built out of data in several fields, ObservableCollection<> of child items, etc. All are there to be bound to the XAML.

I have seen the ViewModel created from the Model as a one-time, one-way process, e.g. with a constructor:

  CustomerViewModel viewModel = new CustomerViewModel(customer);

or as an extension method

  CustomerViewModel viewModel = customer.ToViewModel();

I haven't seen any provision for updating a ViewModel for changes to the Model - the point of the ViewModel is that it's isolated from the model. It keeps a separate copy of the data. It does not propagate changes back to the model, not until you press a "save" button. So if you cancel instead, nothing in the model has changed and there's nothing to undo.

You may be trying too hard to keep the ViewModel up to date with the Model - most cases like save or load you can just throw away the current ViewModel and make a new one from the current state of the model. Do you need to keep the ViewModel's UI state and change the data in it? It's not a common requirement but it could be done with a method or two called when the save or load happens.

So there's also the assumption that this wire-up logic happens somewhere. This is why most patterns that involve views also involve controllers that are responsible for acting on commands (e.g. show a customer, save a customer) and setting up new UI state afterwards.

Anthony
If you keep ViewModel separate from the Model how are any rules in the Model applied? Say I have a Model with Qty and Value. If I change the Qty on the ViewModel that should flow through to the model which updates the Value based on the new Qty. Now the ViewModel should show the new Value.
"If I change the Qty on the ViewModel that should flow through to the model" no, not until you press a Save button or the like. When you do, the handler for that should update the model, persist it and make a new ViewModel off the new Model state.
Anthony
So if it doesn't flow through to the Model, then how does the ViewModel ever get an updated Value field? If I change the Qty, as a user I would expect to see the new Value. The MV doesn't have the business logic to calc Value, only the Model does.
+4  A: 

Your ViewModel doesn't have to encapsulate the Model that strictly. In your scenario, the CustomerViewModel might have a Customer property, which in the end means your View binds to the Model properties... it just does so through the ViewModel. That's perfectly legitimate. That said, however, there's often a benefit to encapsulating this. Your business model may not include change notification. You may not want the user interaction to modify the business model until the user clicks an OK button. Your business model may through exceptions for bad input, while you want to use another form of validation. I'm sure you can think of other things. In fact, I'd guess that most of the time you're going to want the encapsulation, so it's not really "tedious" in the sense of just writing a lot of pointless relay methods.

wekempf
A: 

Exactly how this is done, will depend in part on your business model as wekempf has already stated.

Depending on how your displaying Customer info in your UI, you might have an ObservableCollection of Customer(your model) types in your ViewModel. If, for example, you're displaying a master/detail scenario, where you might have a list of customers and show details below when a particular customer is selected.

Steve Brouillard