12

I am building an application that is based on MVVM-Light. I am in the need of creating multiple instances of the same View, and each one should bind to its own ViewModel.

The default ViewModelLocator implements ViewModels as singletons, therefore different instances of the same View will bind to the same ViewModel.

I could create the ViewModel in the VMLocator as a non-static object (as simple as returning new VM()...), but that would only partially help me. In fact, I still need to keep track of the opened windows. Nevertheless, each window might open several other windows (of a different kind, though). In this situation I might need to execute some operation on the parent View and all its children. For example before closing the View P, I might want to close all its children (view C1, view C2, etc.).

Hence, is there any simple and easy way to achieve this? Or is there any best practice you would advice me to follow?

Thanks in advance for your precious help.

Cheers,
Gianluca.

MasterMastic
  • 20,711
  • 12
  • 68
  • 90
Anthares
  • 1,041
  • 1
  • 13
  • 30
  • Ok, I am not sure I am on the right path, but I found an interesting article (by John Papa - http://johnpapa.net/silverlight/simple-viewmodel-locator-for-mvvm-the-patients-have-left-the-asylum/) and I am trying to implement a ViewModelLocator in that way. Though, I am still not sure how to proceed to handle a specific View amongst the many I might create... – Anthares May 14 '10 at 08:24

3 Answers3

11

There is no obligation to store the ViewModels as singletons in the ViewModelLocator, but it certainly makes them easier to find if the view is a singleton too. Obviously, if you have multiple instances of the same View class, you will have multiple instances of the same ViewModel class, and it cannot be a singleton anymore.

To keep track of the multiple instances of the ViewModel, you can implement a dictionary in the ViewModelLocator that looks up for a ViewModel according to a key. The key can be a unique ID for the view, for example. Once you get hold of the view, retrieve its key and then retrieve the viewmodel from the locator.

Update: Often you don't even need to track multiple viewmodels. For instance, you can have the Messenger class send a message to all instances of a given viewmodel class using the Send overload. So before implementing a dictionary to keep track of the VMs, ask yourself if you really need it! ;)

Hope that helps, Laurent

LBugnion
  • 6,672
  • 2
  • 24
  • 28
  • Thank you Laurent for your reply. For sure I'll need to dig this deeper. By the way, I've seen that many are using MEF instead of a proper ViewModel Locator... so, I am experimenting that solution too. Regarding the "window handler", I tried different approaches but I havent found yet the best for my case ;) Thanks for all your help. Gianluca. – Anthares May 19 '10 at 10:40
  • I have an app with multiple modules using mef, from a module i need to show a view in another module , the calling view listens for the message of the view showed in another module, from the view showed it may create another instance of the same view, now the common messages became a problem two instances of the view send same messages, How can i solve this in a correct manner, Assign every view instance and id something ? – Priyan R Sep 08 '10 at 07:53
  • @Gianluca: The best approach in my experience is to combine a ViewModelLocator with either MEF or an IOC container (NInject, Unity or else). – LBugnion Sep 10 '10 at 11:50
  • @Priyan: The best way is probably to ID your views, and send the ID together with the message. For example, if you derive your message from MessageBase (not compulsory, but possible), you can set a sender property in the message. This gives an indication of who sent the message. – LBugnion Sep 10 '10 at 11:52
  • 3
    @LBugnion So as a programmer this answer makes sense, it is even exactly why I am here. However, as someone new to WPF and MVVM Light I can implement the dictionary and write GetViewModel(string key). But now what? Do I pass in the key to the View and it sets up its VM in the code behind constructor? Or is there a magical MVVM Light way to do this from XAML the same way as the Singletons? – Dirk Bester Jun 08 '14 at 20:16
0

I had a problem posted and solved in this SO question. It turned out to be very much related to Mr Bugnion's answer here (which helped me tremendously, thank you!)

What I've found is you don't need to store the view-model property in ViewModelLocator at all. Just use ServiceLocator to create an instance with a key, and in your "Dialog Service", pass the key to ShowDialog<T>(string key = null).

Also, as mentioned in this thread already, use method Messenger.Default.Send and remember to call viewModel.Cleanup() afterwards to unregister the view-model from Messenger, thereby preventing phantom view-models from trying to process future messages sent to all instances of the view-model class type.

Community
  • 1
  • 1
Riegardt Steyn
  • 5,431
  • 2
  • 34
  • 49
0

I used the naming system of the unity container.

See "How to distinguish multiple view/view model pairs using unity container".

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
BoboProg
  • 121
  • 1
  • 1
  • 8