views:

109

answers:

3

I'm currently working on what will be my first real foray into using MVVM and have been reading various articles on how best to implement it.

My current thoughts are to use my data models effectively as data transfer objects, make them serializable and have them exist on both the client and server sides. It seems like a logical step given that both object types are really just collections of property getters and setters and another layer in between seems like complete overkill.

Obviously there would be issues with INotifyPropertyChanged not working correctly on the server side as there is no ViewModel to which to communicate, but as long as we are careful about constructing our proper domain model objects from data models in the service layer and not dealing the the data models on the server side I don't think it should be a big issue.

I haven't found too much info about this approach in my reading, so I would like to know if this is a pretty standard thing, is this just assumed to be the de facto way of doing MVVM in a multi-tier environment? If I've got completely the wrong idea about things then thoughts on other approaches would be appreciated too.

+1  A: 

Hi, I'm no expert on this. I had just the same scenario. I agree with you that that is quite an overkill. I've been using this solution for quite some time now and haven't encountered any issues. The INotifyPropertyChanged isn't a big problem for me since nothing on the server-side will subscribe to the PropertyChanged event. If you will use inheritance on your data models, then all must be serializable. In my scenario, I have two base classes for my data models: one that is used for data transfer, and the other not.

Michael Detras
Thanks, it seems that there is no real defined consensus at the moment. Given that you have done a similar thing before with no issues I'll accept this one as the answer.
JonC
A: 

You can use whatever model you feel comfortable with, yes all of your properties will need INotifyPropertyChanged behavior. How this will effect the service layer is entirely down to your implementation.

I'm assuming that you ment that you bind to your DTO's in your view?

How I see it is that there is an impedence mismatch between the layers of the application, that is your Domain Model probably looks simliar to your Relational Model, with subtle but crucial differences. There is also a mismatch between the Domain Model and your DTO's (objects may be flattened, computed properties, etc, ...). It's tempting to bind directly to the DTO's as they are probably designed to have what you need for the particular operation, however there is also an impedence mismatch between the DTO and what is needed by the view in order to acheive the desiged outcome. This is where the View Model comes in. The view model has responsibility to proxying the DTO properties to the view, it is responsible for letting the view know if there are validation errors, and routes commands to the appropriate handler (Save, Delete, etc, ...).

I tend to set things up in the following way :

// POCO object. Serializable.
public class AddressDto 
{    
   public int Id { get; set; }
   public string Street { get; set; }    
   public string City { get; set; }    
   public string Country { get; set; } 
}

// IDataErrorInfo for validation.
public class AddressViewModel : INotifyPropertyChanged, IDataErrorInfo
{
   private readonly AddressDto addressDto;

   public AddressViewModel(AddressDto addressDto)
   {
      this.addressDto = addressDto;      
   }

   public int Id { /* get and set for property changed event and update dto */ }
   public string Street { /* get and set for property changed event and update dto  */ }
   public string City { /* get and set for property changed event and update dto  */ }
   public string Country { /* get and set for property changed event and update dto  */ }
   ...

   // IDataErrorInfo implementation
}

public class EditAddressViewModel : INotifyPropertyChanged
{
   public AddressViewModel Address { /* get and set for property changed event */ }
   public ICommand Save { /* setup command */ }
   public ICommand Cancel { /* setup command */ }

   private void Save()
   {
   }

   private void Cancel()
   {
   }
}

Your EditAddressView would then bind to the EditAddressViewModel. Basically the rule is all of your UI behavior should be expressed in terms of your view model.

Yes that does mean extra work, howerver there are things you can do to simplify things a bit (code generation etc). I'm actually working on a library that aims to simplify whole MVVM process using a fluent api. Check it out at http://fluentviewmodel.codeplex.com/

bobble79
A: 

I decided to have a property "Model" on my ViewModel. In the model itself I already implement IPropertyNotifyChanged and IDataErrorInfo. In my ViewModel I thus skip properties where the code would simply "fall-through" to the model. Instead, the View binds directly to the model for those properties.

For more complicated cases, where I have to adjust the data in the model to fit the view, I do this in the ViewModel. Also, the commands, etc. are in the ViewModel. But I do not see the reason to have boilerplate code in the ViewModel repeating the same stuff which I already have in the model.

Daniel Rose