Whats new in PRISM 5.0 – ViewModel Locator

December 04, 2014
Whats new in PRISM 5.0 – ViewModel Locator

ViewModels are usually resolved and injected through DI containers. We will set the viewmodel as DataContext of View. But still there are some frameworks like Caliburn Micro who provided a conventional way of resolving the view models. Now Microsoft added this feature into the PRISM framework. The View and ViewModels can be wired together by a naming convention.

mvvm

In this project the Views and ViewModels followed a naming convention, which can be identified by the framework.

<ViewName> => Home
<ViewName> + ViewModel => HomeViewModel

To initialize this view model location, view should implement the IView interface and AutoWire property should be true for the View.

    public partial class Home : UserControl, IView
{
public Home()
{
InitializeComponent();
}
}
<UserControl x:Class="WpfApplication16.Views.Home"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Mvvm;assembly=Microsoft.Practices.Prism.Mvvm.Desktop"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<TextBlock Text="{Binding Message}" />
</Grid>
</UserControl>

Sometimes this naming convention may not suitable for some applications. So if people want to follow a different convention, still they can consume this awesome feature. It means, it is possible to override the ViewModel locating logic. How cool it is.. huh..!!!

I usually want to add View suffix to my Views (HomeView). So the locator code should change a bit like this,

mvvm

    public partial class App : Application
{
private const string ViewNamespace = "Views";
private const string ViewModelNamespace = "ViewModels";

protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
{
var friendlyName = viewType.FullName.Remove(viewType.FullName.Length - 4);
friendlyName = friendlyName.Replace(ViewNamespace, ViewModelNamespace);
var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
var viewModelName = String.Format(CultureInfo.InvariantCulture, "{0}ViewModel, {1}", friendlyName, viewAssemblyName);
return Type.GetType(viewModelName);
});
}
}

Also it is possible to let your DI container resolve your viewmodel. Just the ViewModel locator will change something like this. I used UnityContainer here.

        protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
IUnityContainer _container = new UnityContainer();
ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
{
return _container.Resolve(type);
});
}