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.
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 ;)