views:

979

answers:

6

It seems that ViewModels that I make look suspiciously like other classes and they seem to require a lot of code repetition, e.g. in a current project I have:

  • SmartForm: Model that represents a data form to fill in, has properties:
    • IdCode
    • Title
    • Description
    • collection of SmartFormFields
    • etc.
  • SmartFormControlView View
  • SmartFormControlViewModel ViewModel
    • IdCode
    • Title
    • Description
    • collection of SmartFormFields
    • etc.

So my ViewModel is basically the same as my Model, just with all the OnPropertyChanged features for binding with the View.

It seems as I refactor and extend this that every little change I make to my model, I have to make a mirror change to the ViewModel.

This seems to violate a basic rule of patterns Don't Repeat Yourself.

Am I implementing the MVVM pattern incorrectly or is it just an inherent characteristic of MVVM that there is always a 1-to-1 repetition going on between Model and ViewModel?

A: 

That's an interesting remark... indeed, it's often necessary to modify the ViewModel to reflect the changes in the Model.

It would be nice if it could be automatic... actually I think it could be possible, by implementing ICustomTypeDescriptor in the ViewModel : GetProperties would return all the properties of the model through reflection. However I'm not sure it would make sense, because the model may not consist of properties at all : it could be methods, fields, or anything, and not everything in the model would be useful in the ViewModel.

Thomas Levesque
currently I'm handling it through snippets and code generation, I would suspect/hope that there will be more support for MVVM coming with new version of WPF and Visual Studio so that ViewModels can be created perhaps with Entity Frameworks, etc. perhaps this is already possible in EF 4.0?
Edward Tanguay
"perhaps this is already possible in EF 4.0?" : well, I didn't see anything specific about MVVM in .NET 4.0... Perhaps Microsoft will provide something in the form of a toolkit, like they did initially for ASP.NET AJAX, and the WPF toolkit (which has been partially included in WPF 4)
Thomas Levesque
+1  A: 

I only know MVC and in MVC a Model-Class which contains GUI is some error. SmartForm seems to be a Form, which means it is not a model. I don't know what you are trying to program but I give you an example for a Model:

Take a Calender. You can ask the Class what date it is today, what month, how many days each month has, ... It has no graphical representation though. The View (CalenderViewMonth or whater you want) prints a single Month on screen. It knows a Calender and asks him what to write in the different cells.

Essentially - you might have something wrong in your modeling / understanding of MVVM (which is a modern .NET-Variant of MVC).


Edit:

I just looked up MVVM on Wikipedia. Model is just like the Model in MVC. View like the View in MVC as well - only graphical representation. the ViewModel is the Glue between a generic View and a specialized Model. Some kind of Adapter. There should be no violation of DRY.

Tobias Langner
SmartForm is just a data holder that determines how a UI Form will look, in MVVM, the View would just connect to the Model if it could, but the Model doesn't have any "binding magic" (OnPropertyChanged, ObservableCollection) and so you have to create a ViewModel which is basically the same as the Model but has these binding features, a ViewModel might not have to implement ALL of the properties and functionality of the model for a specific view, but in my experience it often does and so VM = M + binding magic.
Edward Tanguay
I agree, the duplication here comes from a useless layer (SmartForm).
Nicolas Dorier
+11  A: 

I personally don't think it violates DRY since the model and view-model (I prefer the term presenter) don't point to the same information. For instance your VM and M both have a Title property, but your VM's Title property could also include validation, whereas your model's Title property could assume validity.

While it's true that The VM may contain all of the properties of the model, there is also the possibility of having validations (e.g. Title must be non-blank), data-dependencies, bindable UI-specific properties (icons, colors, brushes, etc.) which aren't part of the view.

Essentially all UI patterns have similar "duplication" in the way you state it: namely cascading modifications. Try changing a model in MVC without changing the controller.

That being said, MVVM (or any UI pattern designed to separate UI, logic, and state) can be overly tedious for simple cases such as your example. When logic becomes little more than state-pass through, the value separating the controller/presenter/view-model decreases.

In your specific case, if there really isn't any logic, validation, or UI specific properties that your VM isn't surfacing, and your model doesn't have to be persisted, serialized, or made backwards compatible with an existing structure (or adding the logic to do so in your VM is trivial), I would strongly consider combining the M and VM to avoid creating properties whose sole purpose is to get/set the underlying model's properties.

micahtan
+2  A: 

A simple solution is to have an abstract ViewModel(VM) base class that exposes the model. You can choose this VM in scenarios where it makes sense.

i.e.

public abstract class ViewModelBase<T>
{
    public T Model { get; set; }
}

If you Model has INotifyPropertyChanged implemented your view will get the event. What this does do is give your View access to every property in your Model which isn't what you want some times.

also you can utilize property initializers like this(which I personally have stored in code snippets):

public abstract class SampleViewModel
{
    public int MyProperty
    {
        get { return Model.MyProperty; }
        set
        {
            Model.MyProperty = value;
            OnPropertyChanged("MyProperty");
        }
    }
}

In most circumstances you view will be the one making changes to your VM and when it does any control that is bound to that property will then be told that something happened.

Hope that helps.

Jose
A: 

Others have provided good comments on the roles of the components of the MVC/MVVM patterns. I would like to offer a fundamental observation explaining the repetitiveness no matter which pattern you select.

Generally there will be some sort of repetition between your data layer, business layer and UI layer. After all, in general you have to show each property to the end user (UI), model it's behavior (Business layer) and persist the value (data layer).

As others have pointed out, the property might be treated a bit differently on each layer which explains the fundamental need for some duplication.

When working on systems large enough (or on small projects with the right team), I tend to model this type of information in UML, and use code generation (often coupled with partial classes) to handle the repetitive aspects. As a simple example, the Last Name property might have a requirement (in my UML model) that it limit data to 50 characters. I can generate code to enforce that limit into my UI layer (e.g. by physically limiting input), generate code into my business layer to recheck that limitation ("never trust the UI") by perhaps throwing an Exception if the data is too long, and generate my persistence layer (e.g. NVARCHAR(50) column, appropriate ORM mapping file, etc.).

Eric J.
A: 

One thing that seems to have been missed here and that your simplistic example does not expose is the fact that your Views will often aggregate data that is contained within multiple Domain Model types. In this case your ViewModels will contain references to a number of domain Models (of differing types) thus aggregating a bunch of related data that a particular View may wish to expose.

Simon Fox