In my first post on using Prism and Xamarin Forms Prism and Xamarin Forms I stated that you needed to follow the convention of views being located in a .Views. namespace and view models being located in a .ViewModels. namespace.
In fact this is not quite true. What happens is, if the ViewModelLocator.AutowireViewModel in the view is set to true, only then does Prism attempt to wire up a view model to a view and in fact the first thing it does is to look at whether the programmer has actually registered a view to a view model factory method. Only if this returns null (i.e. no factory has been supplied for a view) does it attempt the convention based approach.
Registering your View/ViewModel mapping
We can see how to register our view models with the following code snippet (this should be in your App.cs)
protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
ViewModelLocationProvider.Register("XamarinTest.Views.MainPage", () => new MainPageViewModel());
}
As you can see in the above code, you need to ensure the full namespace and type name for the view, and yes it’s a magic string which is not great.
Convention based approach
Okay, so assuming no view/view model mapping has been registered for the view, we’ll now look at the convention based approach used in prism. So by default the convention based approach expects the views to be in a Views namespace and the view models to be in a ViewModels namespace, but this can be changed to suit your needs.
For example, some prefer to keep views and view models for a specific set of functionality together within the same folder or namespace as it saves jumping around a project look for each part of the specific functionality. Or maybe you find other was to layout your view/view model files which you prefer. You can assign your on Func to the ViewModelLocationProvider’s static method SetDefaultViewTypeToViewModelTypeResolver to achieve you own view model mapping.
Let’s take a look
// override this method in your App.cs file
protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(AlternateResolver);
}
Next let’s write a simple implementation of a resolver which looks for matching ViewModels by simply expecting them to be in the same namespace etc. as the view
// add this method to your App.cs
private static Type AlternateResolver(Type type)
{
var viewName = type.FullName;
if (String.IsNullOrEmpty(viewName))
return null;
var viewModel = viewName + "ViewModel";
return Type.GetType(viewModel);
}
Note: I had intended to create an assembly lookup method that would search the assembly for matching types but limitation in what we get as part of the PCL and/or Xamarin appears to have scuppered that idea, so in the above code we simply append ViewModel to the view name. Obviously if you name your views with the View suffix, such as MainPageView, then this code is rather simplistic and will expect the view model to be named MainPageViewViewModel, I’ll leave it to the reader to amend the method as required.