Learn Prism’s ViewModelLocator

6 minute read

Learn the section ViewModelLocator from RRISM LIBRARY Documentation.

It’s a translation of that, but as a memo.
If you don’t speak Japanese, go back to English and understand it. .. ..

The ViewModelLocator is used to wire the DataContext of a view to an instance of a ViewModel using a standard naming convention.

The Prism ViewModelLocator has an AutoWireViewModel attached property, that when set to true calls the AutoWireViewModelChanged method in the ViewModelLocationProvider class to resolve the ViewModel for the view, and then set the view’s data context to an instance of that ViewModel.

Add the AutoWireViewModel attached property to each View:
(Google Translate)
The ViewModelLocator is used to wire the view’s DataContext to an instance of the ViewModel using standard naming conventions.

Prism ViewModelLocator has an AutoWireViewModel attached property that, when set to true, calls the AutoWireViewModelChanged method of the ViewModelLocationProvider class to resolve the view’s ViewModel and set the view’s data context to an instance of that ViewModel.

Add the AutoWireViewModel attached property to each view.

<Window x:Class="Demo.Views.MainWindow"
    ...
    xmlns:prism="http://prismlibrary.com/"
    prism:ViewModelLocator.AutoWireViewModel="True">

To locate a ViewModel, the ViewModelLocationProvider first attempts to resolve the ViewModel from any mappings that may have been registered by the ViewModelLocationProvider.Register method (See Custom ViewModel Registrations). If the ViewModel cannot be resolved using this approach, the ViewModelLocationProvider falls back to a convention-based approach to resolve the correct ViewModel type.

This convention assumes:

・ That ViewModels are in the same assembly as the view types
· That ViewModels are in a .ViewModels child namespace
・ That views are in a .Views child namespace
-That ViewModel names correspond with view names and end with “ViewModel.”
(Google Translate)
To find the ViewModel, the ViewModelLocationProvider first tries to resolve the ViewModel from the mappings that may have been registered by the ViewModelLocationProvider.Register method (see Custom ViewModel Registration). If the ViewModel cannot be resolved using this approach, the ViewModelLocationProvider will fall back to the convention-based approach to resolve the correct ViewModel type.

This rule assumes the following:

· The ViewModel is in the same assembly as the viewtype
· ViewModels is in the .ViewModels child namespace
· The view is in the .Views child namespace
-The ViewModel name corresponds to the view name and ends with “ViewModel”.

NOTE
The ViewModelLocationProvider can be found in the Prism.Mvvm namespace in the Prism.Core NuGet package. The ViewModelLocator can be found in the Prism.Mvvm namespace in the platform specific packages (Prism.WPF, Prism.Forms) NuGet package.
(Google Translate)
Caution
The ViewModelLocationProvider is located in the Prism.Mvvm namespace of the Prism.Core NuGet package. ViewModelLocator is located in the Prism.Mvvm namespace of platform-specific packages (Prism.WPF, Prism.Forms) NuGet packages.

NOTE
The ViewModelLocator is required, and automatically applied to every View, when developing with Xamarin.Forms as it is responsible for providing the correct instance of the INavigationService to the ViewModel. When developing a Xamarin.Forms app, the ViewModelLocator is opt-out only.
(Google Translate)
Caution
When developing with Xamarin.Forms, the ViewModelLocator is required and must provide the ViewModel with the correct instance of INavigationService, so it will be automatically applied to all views. When developing a Xamarin.Forms app, ViewModelLocator is opt-out only.

image.png

Change the Naming Convention
If your application does not follow the ViewModelLocator default naming convention, you can change the convention to meet the requirements of your application. The ViewModelLocationProvider class provides a static method called SetDefaultViewTypeToViewModelTypeResolver that can be used to provide your own convention for associating views to view models.

To change the ViewModelLocator naming convention, override the ConfigureViewModelLocator method in the App.xaml.cs class. Then provide your custom naming convention logic in the ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver method.
(Google Translate)
If your application does not follow ViewModelLocator’s default naming convention, you can modify the convention to meet your application’s requirements. The ViewModelLocationProvider class provides a static method called SetDefaultViewTypeToViewModelTypeResolver that you can use to provide your own rules for associating a view with a view model.

To change the ViewModelLocator naming convention, override the ConfigureViewModelLocator method in the App.xaml.cs class. Then provide custom naming convention logic with the ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver method.

protected override void ConfigureViewModelLocator()
{
    base.ConfigureViewModelLocator();

    ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
    {
        var viewName = viewType.FullName.Replace(".ViewModels.", ".CustomNamespace.");
        var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
        var viewModelName = $"{viewName}ViewModel, {viewAssemblyName}";
        return Type.GetType(viewModelName);
    });
}

image.png

Custom ViewModel Registrations
There may be instances where your app is following the ViewModelLocator default naming convention, but you have a number of ViewModels that do not follow the convention. Instead of trying to customize the naming convention logic to conditionally meet all your naming requirments, you can register a mapping for a ViewModel to a specific view directly with the ViewModelLocator by using the ViewModelLocationProvider.Register method.

The following examples show the various ways to create a mapping between a view called MainWindow and a ViewModel named CustomViewModel.
(Google Translate)
Your app may follow the ViewModelLocator’s default naming convention, but there are some ViewModels that don’t. Instead of customizing the naming convention logic to conditionally meet all naming requirements, you can use the ViewModelLocationProvider.Register method to directly register the ViewModel’s mapping to a particular view in ViewModelLocator.

The following examples show different ways to create a mapping between a view named MainWindow and a ViewModel named CustomViewModel.
Type / Type

ViewModelLocationProvider.Register(typeof(MainWindow).ToString(), typeof(CustomViewModel));

Type / Factory

ViewModelLocationProvider.Register(typeof(MainWindow).ToString(), () => Container.Resolve<CustomViewModel>());

Generic Factory

ViewModelLocationProvider.Register<MainWindow>(() => Container.Resolve<CustomViewModel>());

Generic Type

ViewModelLocationProvider.Register<MainWindow, CustomViewModel>();

NOTE
Registering your ViewModels directly with the ViewModelLocator is faster than relying on the default naming convention. This is because the naming convention requires the use of reflection, while a custom mapping provides the type directly to the ViewModelLocator.
(Google Translate)
Caution
Registering the ViewModel directly with the ViewModelLocator is faster than relying on the default naming convention. This is because naming conventions require the use of reflection, but custom mapping provides the type directly to the ViewModelLocator.

IMPORTANT
The viewTypeName parameter must be the fully qualifyied name of the view’s Type (Type.ToString()). Otherwise the mapping will fail.
(Google Translate)
important
The viewTypeName parameter must be the fully qualified name of the view type (Type.ToString ()). Otherwise, the mapping will fail.

image.png

Control how ViewModels are Resolved
By default, the ViewModelLocator will use the DI container you have chosen to create your Prism application to resolve ViewModels. However, if you ever have the need to customize how ViewModels are resolved or change the resolver altogether, you can achieve this by using the ViewModelLocationProvider.SetDefaultViewModelFactory method.

This example shows how you might change the container used for resolving the ViewModel instances.
(Google Translate)
By default, ViewModelLocator uses the DI container of your choice to create a Prism application and resolve the ViewModel. However, if you need to customize the ViewModel’s solution or completely change the resolver, you can do this using the ViewModelLocationProvider.SetDefaultViewModelFactory method.

This example shows how to change the container used to resolve a ViewModel instance.

protected override void ConfigureViewModelLocator()
{
    base.ConfigureViewModelLocator();

    ViewModelLocationProvider.SetDefaultViewModelFactory(viewModelType) =>
    {
        return MyAwesomeNewContainer.Resolve(viewModelType);
    });
}

This is an example of how you might check the type of the view the ViewModel is being created for, and performing logic to control how the ViewModel is created.
(Google Translate)
This is an example of how to check the type of view in which the ViewModel is created and execute the logic that controls how the ViewModel is created.

protected override void ConfigureViewModelLocator()
{
    base.ConfigureViewModelLocator();

    ViewModelLocationProvider.SetDefaultViewModelFactory((view, viewModelType) =>
    {
        switch (view)
        {
            case Window window:
                //your logic
                break;
            case UserControl userControl:
                //your logic
                break;
        }

        return MyAwesomeNewContainer.Resolve(someNewType);
    });
}