Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I apologize for the long question, it reads a bit as a rant, but I promise it's not! I've summarized my question(s) below

In the MVC world, things are straightforward. The Model has state, the View shows the Model, and the Controller does stuff to/with the Model (basically), a controller has no state. To do stuff the Controller has some dependencies on web services, repository, the lot. When you instantiate a controller you care about supplying those dependencies, nothing else. When you execute an action (method on Controller), you use those dependencies to retrieve or update the Model or calling some other domain service. If there's any context, say like some user wants to see the details of a particular item, you pass the Id of that item as parameter to the Action. Nowhere in the Controller is there any reference to any state. So far so good.

Enter MVVM. I love WPF, I love data binding. I love frameworks that make data binding to ViewModels even easier (using Caliburn Micro a.t.m.). I feel things are less straightforward in this world though. Let's do the exercise again: the Model has state, the View shows the ViewModel, and the ViewModel does stuff to/with the Model (basically), a ViewModel does have state! (to clarify; maybe it delegates all the properties to one or more Models, but that means it must have a reference to the model one way or another, which is state in itself) To do stuff the ViewModel has some dependencies on web services, repository, the lot. When you instantiate a ViewModel you care about supplying those dependencies, but also the state. And this, ladies and gentlemen, annoys me to no end.

Whenever you need to instantiate a ProductDetailsViewModel from the ProductSearchViewModel (from which you called the ProductSearchWebService which in turn returned IEnumerable<ProductDTO>, everybody still with me?), you can do one of these things:

  • call new ProductDetailsViewModel(productDTO, _shoppingCartWebService /* dependcy */);, this is bad, imagine 3 more dependencies, this means the ProductSearchViewModel needs to take on those dependencies as well. Also changing the constructor is painful.
  • call _myInjectedProductDetailsViewModelFactory.Create().Initialize(productDTO);, the factory is just a Func, they are easily generated by most IoC frameworks. I think this is bad because Init methods are a leaky abstraction. You also can't use the readonly keyword for fields that are set in the Init method. I'm sure there are a few more reasons.
  • call _myInjectedProductDetailsViewModelAbstractFactory.Create(productDTO); So... this is the pattern (abstract factory) that is usually recommended for this type of problem. I though it was genius since it satisfies my craving for static typing, until I actually started using it. The amount of boilerplate code is I think too much (you know, apart from the ridiculous variable names I get use). For each ViewModel that needs runtime parameters you'll get two extra files (factory interface and implementation), and you need to type the non-runtime dependencies like 4 extra times. And each time the dependencies change, you get to change it in the factory as well. It feels like I don't even use a DI container anymore. (I think Castle Windsor has some kind of solution for this [with it's own drawbacks, correct me if I'm wrong]).
  • do something with anonymous types or dictionary. I like my static typing.

So, yeah. Mixing state and behavior in this way creates a problem which don't exist at all in MVC. And I feel like there currently isn't a really adequate solution for this problem. Now I'd like to observe some things:

  • People actually use MVVM. So they either don't care about all of the above, or they have some brilliant other solution.
  • I haven't found an in-depth example of MVVM with WPF. For example, the NDDD-sample project immensely helped me understand some DDD concepts. I'd really like it if someone could point me in the direction of something similar for MVVM/WPF.
  • Maybe I'm doing MVVM all wrong and I should turn my design upside down. Maybe I shouldn't have this problem at all. Well I know other people have asked the same question so I think I'm not the only one.

To summarize

  • Am I correct to conclude that having the ViewModel being an integration point for both state and behavior is the reason for some difficulties with the MVVM pattern as a whole?
  • Is using the abstract factory pattern the only/best way to instantiate a ViewModel in a statically typed way?
  • Is there something like an in depth reference implementation available?
  • Is having a lot of ViewModels with both state/behavior a design smell?
share|improve this question
8  
This is too long to read, consider revising, there's a lot of irrelevant stuff in there. You might miss good answers because people won't bother to read all that. –  Yannis Rizos Nov 2 '12 at 10:55
    
You said you love Caliburn.Micro, yet you don't know how this framework can help instantiate new view models? Check some examples of it. –  Euphoric Nov 2 '12 at 11:43
    
@Euphoric Could you be a bit more specific, Google doesn't seem to help me here. Got some keywords I could search for? –  dvdvorle Nov 2 '12 at 12:48
3  
I think you're simplifying MVC a bit. Sure the View shows the Model at the beginning, but during operation it's changing state. This changing state is, in my opinion, an "Edit Model". That is, a flattened version of the Model with reduced consistency restrictions. In fact, what I call an Edit Model is the MVVM ViewModel. It holds the state while in transition, that was previously held by either the View in MVC, or pushed back into an uncommitted version of the Model, where I don't think it belongs. So you had state "in flux" before. Now it's all in the ViewModel. –  Scott Whitlock Nov 2 '12 at 15:26
    
@ScottWhitlock I am simplifying MVC indeed. But I'm not saying it's wrong that the state "in flux" is in the ViewModel, I'm saying that cramming the behavior in there as well makes it harder to initialize the ViewModel to a usable state from say, another ViewModel. Your "Edit Model" in MVC doesn't know how to Save itself (it doesn't have a Save method). But the controller does know this, and has all the dependencies needed to do that. –  dvdvorle Nov 2 '12 at 16:16

4 Answers 4

I work daily with ASP.NET MVC and have worked on a WPF for over a year and this is how I see it:

MVC

The controller is supposed to orchestrate actions (fetch this, add that).

The view is responsible for displaying the model.

The model typically encompasses data (ex. UserId, FirstName) as well as state (ex. Titles) and is usually view specific.

MVVM

The model typically only holds data (ex. UserId, FirstName) and is usually passed around

The view model encompasses the behavior of the view (methods), its data (model) and interactions (commands) - similar to the active MVP pattern where the presenter is aware of the model. The view model is view specific (1 view = 1 view model).

The view is responsible for displaying data and data-binding to the view model. When a view is created, usually its associated view model is created with it.


What you should remember is that the MVVM presentation pattern is specific to WPF/Silverlight due to their data-binding nature.

The view typically knows which view model its associated with (or an abstraction of one).

I would advise that you treat the view model as a singleton, even though it's instantiated per view. In other words, you should be able to create it via DI via an IOC container and call appropriate methods upon it to say; load its model based on parameters. Something like this:

public partial class EditUserView
{
    public EditUserView(IContainer container, int userId) : this() {
        var viewModel = container.Resolve<EditUserViewModel>();
        viewModel.LoadModel(userId);
        DataContext = viewModel;
    }
}

As an example in this case, you wouldn't create a view model specific to the user being updated - instead the model would contain user specific data that gets loaded via some call on the view model.

share|improve this answer
    
If my FirstName is "Peter" and my Titles are {"Rev", "Dr"} *, why do you consider FirstName data and Title state? Or can you clarify your example? * not really –  Pete Kirkham Mar 6 '13 at 11:00
    
@PeteKirkham - the 'titles' example I was referring to in the context of say a combobox. Generally when you send information to be persisted you won't be sending the state (ex. a list of states/provinces/titles) that was used to make selections from. Any worthwhile state to transfer with the data (ex. is the username in use) should be checked at the point of processing because the state might have become stale (if you were using some asynchronous pattern such as message queuing). –  Shelakel Mar 8 '13 at 19:45

The issue of dependencies when initiating a new view model can be handled with IOC.

public class MyCustomViewModel{
  private readonly IShoppingCartWebService _cartService;

  private readonly ITimeService _timeService;

  public ProductDTO ProductDTO { get; set; }

  public ProductDetailsViewModel(IShoppingCartWebService cartService, ITimeService timeService){
    _cartService = cartService;
    _timeService = timeService;
  }
}

When setting up the container...

Container.Register<IShoppingCartWebService,ShoppingCartWebSerivce>().As.Singleton();
Container.Register<ITimeService,TimeService>().As.Singleton();
Container.Register<ProductDetailsViewModel>();

When you need your view model:

var viewmodel = Container.Resolve<ProductDetailsViewModel>();
viewmodel.ProductDTO = myProductDTO;

When utilizing a framework such as caliburn micro there is often some form of IOC container already present.

SomeCompositionView view = new SomeCompositionView();
ISomeCompositionViewModel viewModel = IoC.Get<ISomeCompositionViewModel>();
ViewModelBinder.Bind(viewModel, view, null);
share|improve this answer

The way I usually do this (using PRISM), is each assembly contains an container initialisation module, where all the interfaces, instances are registered on startup.

private void RegisterResources()
{
    Container.RegisterType<IDataService, DataService>();
    Container.RegisterType<IProductSearchViewModel, ProductSearchViewModel>();
    Container.RegisterType<IProductDetailsViewModel, ProductDetailsViewModel>();
}

And given your example classes, would be implemented like this, with the container being passed all the way through. This way any new dependencies can be added easily as you already have access to the container.

/// <summary>
/// IDataService Interface
/// </summary>
public interface IDataService
{
    DataTable GetSomeData();
}

public class DataService : IDataService
{
    public DataTable GetSomeData()
    {
        MessageBox.Show("This is a call to the GetSomeData() method.");

        var someData = new DataTable("SomeData");
        return someData;
    }
}

public interface IProductSearchViewModel
{
}

public class ProductSearchViewModel : IProductSearchViewModel
{
    private readonly IUnityContainer _container;

    /// <summary>
    /// This will get resolved if it's been added to the container.
    /// Or alternately you could use constructor resolution. 
    /// </summary>
    [Dependency]
    public IDataService DataService { get; set; }

    public ProductSearchViewModel(IUnityContainer container)
    {
        _container = container;
    }

    public void SearchAndDisplay()
    {
        DataTable results = DataService.GetSomeData();

        var detailsViewModel = _container.Resolve<IProductDetailsViewModel>();
        detailsViewModel.DisplaySomeDataInView(results);

        // Create the view, usually resolve using region manager etc.
        var detailsView = new DetailsView() { DataContext = detailsViewModel };
    }
}

public interface IProductDetailsViewModel
{
    void DisplaySomeDataInView(DataTable dataTable);
}

public class ProductDetailsViewModel : IProductDetailsViewModel
{
    private readonly IUnityContainer _container;

    public ProductDetailsViewModel(IUnityContainer container)
    {
        _container = container;
    }

    public void DisplaySomeDataInView(DataTable dataTable)
    {
    }
}

It's quite common to have a ViewModelBase class, which all your view models are derived from, which contains a reference to the container. As long as you get into the habit of resolving all view models instead of new()'ing them, it should make all dependency resolution a lot simpler.

share|improve this answer

Sometimes it's good to go to the simplest definition rather than a full-blown example: http://en.wikipedia.org/wiki/Model_View_ViewModel maybe reading the ZK Java example is more illuminating than the C# one.

Other times listen to your gut instinct...

Is having a lot of ViewModels with both state/behavior a design smell?

Are your models are object per table mappings? Perhaps an ORM would help mapping to domain objects while handling the business or updating multiple tables.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.