10039

How to have multiple instances of the same ViewModel in MVVM Light?

Question:

I'm using MVVM Light for a WPF application with tabs (a bit like Internet Explorer). Each tabs has to be a couple of unique View and View models. I know know how many instances I will have in my tab control.

Due to the design of MVVM Light I can't have multiple instances of a ViewModel at the same moment (static property in the locator). On the codeplex Website i found the following solution :

The way I handle this is by making the ViewModel property in the ViewModelLocator (for example the Main property for the MainViewModel) return a different instance of the MainViewModel each time it is called. This way each view will have a separate instance of the MainViewModel.

However, this means that resolving the DataContext of a given window is a bit more complex (since the ViewModel is not kept static anymore). If you need to resolve, you can build a lookup table in the ViewModelLocator based on a unique ID stored in the View for example, or use an IOC container to instantiate and resolve the ViewModel instances according to a key.

I understand I have to inject an ID in each view, I understand I have to maintain a list of these IDs in the Locator, I understand I have to lookup in the locator to associate each view to the right locator, but I have no idea how to pass this ID from my view to the Locator. How can I do that in the XAML of my view ?

I hope my question is clear enough, let me know if you need more details.

Answer1:

What I typically will do is make a list of the view models inside of a view model for the window which holds the tab control. The XMAL to do this looks like this:

<TabControl ItemsSource="View model list here"> <TabControl.ItemTemplate> <DataTemplate> <!-- Your user control here --> </DataTemplate> </TabControl.ItemTemplate> </TabControl>

To solve the view model locator problem because your main view model will contain the view model for each tab and know how to resolve it.

If each tab has unique data then I would still use 1 view model for the window, make the contents of each tab item a custom control and set their datacontext from the main view model.

HTH

Answer2:

I once explained how to use this kind of scenario on my blog here <a href="http://depblog.weblogs.us/2014/02/11/navigating-to-same-viewmodel-but-with-different-data-and-keep-navigation-stack-correct-with-mvvm-light/" rel="nofollow">http://depblog.weblogs.us/2014/02/11/navigating-to-same-viewmodel-but-with-different-data-and-keep-navigation-stack-correct-with-mvvm-light/</a>.

It's for windows phone but would work for WPF too. Only difference with your setup versus mine is that you need to get your unique ID from each tab, as I get mine when navigating to a new view.

So what I would suggest is hook up to the tab changed event and retrieve your key at that point. Not sure how you keep track of your keys in the view, but I guess you have it available, if not you could always store it in some Tag property of the control.

Last but not least is to bind the datacontext with the needed viewmodel, this is how you could do that:

tabControl.DataContext = ViewModelLocator.GetViewModel<***ViewModel>(tabKey);

TabControl being the current active tab ( I'm guessing the datacontext should be set on that? ) TabKey being the unique key for the current selected tab that is needed to retrieve the correct corresponding viewmodel

Sorry for the high level pseudo code but because you didn't add some reference code of your current solution it's a bit guessing work ;)

Recommend

  • So we've got MEF working with MVC4, how about the convention based model?
  • How to change the scope of an existing binding in Ninject
  • Dependency Injection - Choose DLL and class implementation at runtime through configuration file
  • Help designing a order manager class
  • How to lookup value with multiple criteria in excel 2007 and newer
  • C++ stl pop doesn't return [closed]
  • How to remove last utf8 char of a python string
  • DNS Lookup failed - Error with all browsers [closed]
  • Unable to set a breakpoint on main while debugging a program compiled with Rust 1.10 with GDB
  • Excel VBA How to populate a multi-dimensional (3d) array with values from multiple excel ranges?
  • Ruby on Rails App deployed to heroku showing “We're sorry, but something went wrong”
  • How can I replace the server in Web Component Tester
  • jQuery: add elements until a particular height is reached
  • How to use jQuery's $.post() method with async/await and typescript
  • Overlapping controls in Windows XP
  • Keep this build forever option - Jenkins
  • Converting a WriteableBitmap image ToArray in UWP
  • Use of this Javascript
  • Setting up SourceTree to merge unity3d scenes with UnityYAMLMerge
  • Unity3D & Android: Difference between “UnityMain” and “main” threads?
  • C++ Partial template specialization - design simplification
  • Installing Hadoop, Java Exception about illegal characters at index 7?
  • Is there any way to access browser form field suggestions from JavaScript?
  • Fetching methods from BroadcastReceiver to update UI
  • Does CUDA 5 support STL or THRUST inside the device code?
  • Convert array of 8 bytes to signed long in C++
  • Hazelcast - OperationTimeoutException
  • How to get next/previous record number?
  • Delete MySQLi record without showing the id in the URL
  • Unanticipated behavior
  • Comma separated Values
  • How to delete a row from a dynamic generate table using jquery?
  • Python: how to group similar lists together in a list of lists?
  • json Serialization in asp
  • Proper folder structure for lots of source files
  • Rails 2: use form_for to build a form covering multiple objects of the same class
  • Trying to get generic when generic is not available
  • -fvisibility=hidden not passed by compiler for Debug builds
  • How to stop GridView from loading again when I press back button?
  • Net Present Value in Excel for Grouped Recurring CF