How to make creating viewmodels at runtime less painful

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?

9

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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>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;
}
}
</code>
<code>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; } } </code>
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…

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Container.Register<IShoppingCartWebService,ShoppingCartWebSerivce>().As.Singleton();
Container.Register<ITimeService,TimeService>().As.Singleton();
Container.Register<ProductDetailsViewModel>();
</code>
<code>Container.Register<IShoppingCartWebService,ShoppingCartWebSerivce>().As.Singleton(); Container.Register<ITimeService,TimeService>().As.Singleton(); Container.Register<ProductDetailsViewModel>(); </code>
Container.Register<IShoppingCartWebService,ShoppingCartWebSerivce>().As.Singleton();
Container.Register<ITimeService,TimeService>().As.Singleton();
Container.Register<ProductDetailsViewModel>();

When you need your view model:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>var viewmodel = Container.Resolve<ProductDetailsViewModel>();
viewmodel.ProductDTO = myProductDTO;
</code>
<code>var viewmodel = Container.Resolve<ProductDetailsViewModel>(); viewmodel.ProductDTO = myProductDTO; </code>
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>SomeCompositionView view = new SomeCompositionView();
ISomeCompositionViewModel viewModel = IoC.Get<ISomeCompositionViewModel>();
ViewModelBinder.Bind(viewModel, view, null);
</code>
<code>SomeCompositionView view = new SomeCompositionView(); ISomeCompositionViewModel viewModel = IoC.Get<ISomeCompositionViewModel>(); ViewModelBinder.Bind(viewModel, view, null); </code>
SomeCompositionView view = new SomeCompositionView();
ISomeCompositionViewModel viewModel = IoC.Get<ISomeCompositionViewModel>();
ViewModelBinder.Bind(viewModel, view, null);

Short answer for your questions:

  1. Yes State+Behavior leads to those problems, but this is true for all of OO. The real culprit is the coupling of ViewModels which is a kind of SRP violation.
  2. Statically typed, probably. But you should reduce/eliminate your need for instantiating ViewModels from other ViewModels.
  3. Not that I’m aware off.
  4. No, but having ViewModels with unrelated state & behavior (Like some Model references and some ViewModel references)

The long version:

We’re facing the same Problem, and found some things that may help you. Although I do not know the “magic” solution, those things are easing the pain a little.

  1. Implement bindable models from DTOs for change tracking and validation. Those “Data”-ViewModels must not depend upon services and do not come from the container. They can be just “new”ed up, passed around and may even derive from the DTO. Bottomline is to implement a Model specific to your application (Like MVC).

  2. Decouple your ViewModels. Caliburn makes it easy to couple the ViewModels together. It even suggests it through its Screen/Conductor model. But this coupling makes the ViewModels hard to unit test, create a lot of dependencies and most important: Imposes the burden of managing the ViewModel lifecycle upon your ViewModels.
    One way to decouple them is using something like a navigation service or ViewModel controller. E.g.

    public interface IShowViewModels
    {
    void Show(object inlineArgumentsAsAnonymousType, string regionId);
    }

Even better is doing this by some form of messaging. But the important thing is not to handle the ViewModel lifecycle from other ViewModels.
In MVC Controllers do not depend on each other, and in MVVM ViewModels should not depend on each other. Integrate them through some other ways.

  1. Use your containers “stringly”-typed/dynamic features. Although it could be possible creating something like INeedData<T1,T2,...> and enforcing type-safe creation parameters, it is not worth it. Also creating factories for each ViewModel type is not worth it. Most IoC Containers provide solutions to this. You’ll get errors at runtime but the de-coupling and unit testability is worth it. You still do some kind of integration test and those errors are spotted easily.

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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>private void RegisterResources()
{
Container.RegisterType<IDataService, DataService>();
Container.RegisterType<IProductSearchViewModel, ProductSearchViewModel>();
Container.RegisterType<IProductDetailsViewModel, ProductDetailsViewModel>();
}
</code>
<code>private void RegisterResources() { Container.RegisterType<IDataService, DataService>(); Container.RegisterType<IProductSearchViewModel, ProductSearchViewModel>(); Container.RegisterType<IProductDetailsViewModel, ProductDetailsViewModel>(); } </code>
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.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>/// <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)
{
}
}
</code>
<code>/// <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) { } } </code>
/// <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.

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:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public partial class EditUserView
{
public EditUserView(IContainer container, int userId) : this() {
var viewModel = container.Resolve<EditUserViewModel>();
viewModel.LoadModel(userId);
DataContext = viewModel;
}
}
</code>
<code>public partial class EditUserView { public EditUserView(IContainer container, int userId) : this() { var viewModel = container.Resolve<EditUserViewModel>(); viewModel.LoadModel(userId); DataContext = viewModel; } } </code>
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.

3

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.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật