views:

120

answers:

4

In our application we have many Model objects that have hundreds of properties.

For every property on the model:

public string SubscriptionKind { get; set; }
...100x...

we had to make an INotifyPropertyChanged-enabled property on the ViewModel:

#region ViewModelProperty: SubscriptionKind
private int _subscriptionKind;
public int SubscriptionKind
{
    get
    {
        return _subscriptionKind;
    }

    set
    {
        _subscriptionKind = value;
        OnPropertyChanged("SubscriptionKind");
    }
}
#endregion

...100x...

which meant that when our View sent the Save event, we had to remap all these values of the view model back into the model:

customer.SubscriptionKind = this.SubscriptionKind
...100x...

This became tedious and time-consuming as the models kept changing and we had to map all changes up into the ViewModels.

After awhile we realized that it would be more straight-forward to just connect the DataContext of the View directly to the Model which enables us to bind the XAML elements directly to the Model object properties so that the save event would simply save the object without any mapping whatsoever.

What we lost in this move is:

  • the ability via UpdateSourceTrigger=PropertyChanged to do fine-grained validation and manipulation in the ViewModel Property Setters, which I really liked: this we don't have anymore since any change in XAML simple changes the dumb property on the Model

  • the ability (in the future) to create mock views which test our viewmodel's UI logic in a novel way, e.g. "if property SubscriptionKind is set to "Yearly" then (1) change discount to 10%, (2) run "congratulations animation", and (3) make order button more prominent.

Both of these approaches have obvious advantages, e.g. the first way "View-direct-to-Model" approach especially when combined with LINQ-to-SQL is pragmatic and enables you to produce useful software fast, and as long as you use {Binding...} instead of x:Name you still have the ability to "hand off your views to a Blend Designer".

On the other hand, although MVVM requires you to maintain tedious mapping of Model to ViewModel, it gives you powerful validation and testing advantages that the first approach doesn't have.

How have you been able to combine the advantages of these two approaches in your projects?

+1  A: 

Since your ViewModel has access to the model, you can also just directly wrap the model's properties:

#region ViewModelProperty: SubscriptionKindprivate
// int _subscriptionKind; - Use the model directly
public int SubscriptionKind
{
    get
    {
        return this.Model.SubscriptionKind;
    }
    set
    {
        if (this.Model.SubscriptionKind != value)
        {
            this.Model.SubscriptionKind = value;
            OnPropertyChanged("SubscriptionKind");
        }
    }
}
#endregion

The advantage here is you can keep your validation in place in the ViewModel if you wish, and have more control over how it's set back to your model, but there is less duplication in place.

Reed Copsey
A: 

Since my model objects are business objects, not directly related to the datamodel, I use them directly in the ViewModel.

The first mapping (datamodel to business object model) and the creation of properties are generated by a code generator.

Eduardo Molteni
+1  A: 

Why not use a mapping tool like AutoMapper? It's speedy and you don't have to write all of that mapping code:

Mapper.CreateMap<MyModel, MyViewModel>();
MyViewModel vm = Mapper.Map(myModelInstance);

Really easy and now you get the best of both worlds.

Automapper uses a technique that generates assemblies on the fly to do the mapping. This makes it execute just as fast as if you had written all of that tedious mapping code, but you don't have to.

Anderson Imes
A: 

I used a t4 Generator class to create my ViewModels from XAML not sure if this would help your situation.

vsmike