Where is ExportViewModel and ViewModelCreator on Metro?

Aug 22, 2012 at 10:41 PM

I'm attempting to use the MvvmHelpers project on a WinRT project. However, I'm not sure on the right approach to IoC. I have half a dozen user controls. Some use one ViewModel, some another. I saw your post about the ExportViewModel attribute, but I don't see that in the current WinRT library. Also, it wasn't clear whether or not ViewModelCreator makes a new instance every time or reuses the same instance. I only want one instance of my ViewModels, ever.

Coordinator
Aug 23, 2012 at 10:44 PM
Great question. Yes, that's missing from the public build currently - MEF changed quite a bit and I hadn't worked out the best solution. I think I have one now so let me check it in and you can pull it and try it out before I push it into the public build.

Thanks!
mark

From: brantheman

I'm attempting to use the MvvmHelpers project on a WinRT project. However, I'm not sure on the right approach to IoC. I have half a dozen user controls. Some use one ViewModel, some another. I saw your post about the ExportViewModel attribute, but I don't see that in the current WinRT library. Also, it wasn't clear whether or not ViewModelCreator makes a new instance every time or reuses the same instance. I only want one instance of my ViewModels, ever.


Coordinator
Aug 24, 2012 at 11:48 PM
Edited Sep 4, 2012 at 12:32 AM
The support is in the trunk, I'll update the binaries shortly - watch for 1.01.
The default behavior is to create non-shared components. If you want the imports to be shared, you need to add [Shared] onto your export.
So, for ViewModels, just do this:
[ExportViewModel("theVM")]
public class MainViewModel : ViewModel
{
}
and then, in your View, use a ViewModelLocator, there are no custom markup extensions in Metro so for this release, just create a global locator and then use either the method Locate/TryLocate or use the ViewModel dictionary to get at the VM.
For code behind:
DataContext = ServiceLocator.Instance.Resolve<IViewModelLocator>().Locate("theVM");

or in XAML:
<Page.Resources>
 <Mvvm:ViewModelLocatorResource x:Key="VMLocator" />
</Page.Resources>

 

<Grid  Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
  DataContext="{Binding ViewModels[theVM], Source={StaticResource VMLocator}}">

For multi-page apps, put the locator into App resources and bind the Page.DataContext of course.
Hope that helps!
mark
[Edit: modified post based on changes in 1.03]
Coordinator
Aug 25, 2012 at 12:00 AM

Binaries and Nuget have been updated.

Aug 29, 2012 at 2:57 PM

That looks good. Thanks.

Coordinator
Sep 4, 2012 at 12:31 AM

The latest version 1.03 has a breaking change in the ViewModelLocator.  Specifically, I ran into an issue where I had multiple VM locators (and they were creating independent ViewModels) because one was in resources and the other was created from MEF as a service.  To fix this, I've removed the public ViewModelLocator - it's now internal, and exposed an IViewModelLocator interface instead.  You can retrieve this with MEF:

[Import]
public IViewModelLocator Views {get;set;}

or with the built-in service locator:

IViewModelLocator locator = ServiceLocator.Instance.Resolve<IViewModelLocator>();

and in XAML, you use the new ViewModelLocatorResource which does the above to get the same shared instance.  Here's an example:

<Page.Resources>
   <j:ViewModelLocatorResource x:Key="VMLocator" />
</Page.Resources>

otherwise, the syntax is the same (it has a ViewModels dictionary indexer to retrieve by key).

Hopefully this won't be too much of a break for people, but it fixes a very troubling issue when trying to access a shared view model!

mark