6
votes

When starting a new mvvm-wpf-application, I usually include mvvm-light right at the start. That works fine, until my application grows.

Some where along the line the ViewModelLocator becomes huge (many ViewModels for all kinds of ChildViewodels). And even further down the rabbit hole I need multiple distinct instances of the same viewmodel. (eg for a List of items, with which one would like to interact on the same screen). This is where the struggle begins, how to handle that nice, consistently en keep the code testable?

So, if i want to get rid of the ViewModelLocator (is it an antipattern? is feels like a ServiceLocator) should I move to ViewModel-first and create (many) abstract factories for all ViewModels?

2

2 Answers

0
votes

The ViewModelLocator is a fancy name for a Navigation Bus used for Inversion of Control (IoC). Though this appears to be a newer technology, a navigation bus is really using a Service Bus in a different way. It is not anti-pattern if you have a static (shared in VB) container. The anti-pattern comes in if you are passing the container around in your ViewModels.

The thing to keep in mind in MVVM is that it is versatile design pattern, and you can extend it in many ways. The best solution for large projects is component design (a design where each feature of your application is in it's own namespace or project).

A design diagram may look like so:

  • Customer
    • Models
    • ViewModels
    • Services
  • Orders
    • Models
    • ViewModels
    • Services

etc... It really comes down to the flavor of the developer. As long as your design is consistent.

Further reading: To better understand the ViewModelLocator search for the Navigation Bus. To better understand the EventAggregator, search for Message Bus

0
votes

Well, yes, if you use the built in IOC container with MVVMLight. If you use things like AutoFac or Ninject, you can register all classes that are based on ViewModelBase. Another option is to use code generation to generate the ViewModelLocator. With the two approaches, you can get it down to one line per view model.

public MyViewModel MyView => serviceLocator.Resolve<MyViewModel>();