Prism の ViewModelLocator を学ぶ

[RRISM LIBRARY の Documentation から ViewModelLocator](https://prismlibrary.com/docs/viewmodel-locator.html) の箇所を学んでみます。

そのまんまの翻訳ですが、メモとして。
日本語がへんなところは英語に戻ってそれなりに理解。。。

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翻訳)
ViewModelLocatorは、標準の命名規則を使用して、ビューのDataContextをViewModelのインスタンスにワイヤリングするために使用されます。

Prism ViewModelLocatorにはAutoWireViewModel添付プロパティがあり、trueに設定すると、ViewModelLocationProviderクラスのAutoWireViewModelChangedメソッドを呼び出してビューのViewModelを解決し、ビューのデータコンテキストをそのViewModelのインスタンスに設定します。

AutoWireViewModel添付プロパティを各ビューに追加します。

```
<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翻訳)
ViewModelを見つけるために、ViewModelLocationProviderはまず、ViewModelLocationProvider.Registerメソッドによって登録されている可能性のあるマッピングからViewModelを解決しようとします（カスタムViewModel登録を参照）。 このアプローチを使用してViewModelを解決できない場合、ViewModelLocationProviderは、正しいViewModelタイプを解決するために、コンベンションベースのアプローチにフォールバックします。

この規則は、以下を前提としています。

・ViewModelがビュータイプと同じアセンブリにあること
・ViewModelsが.ViewModels子名前空間にあること
・そのビューが.Views子名前空間にあること
・ViewModel名がビュー名に対応し、「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翻訳)
注意
ViewModelLocationProviderは、Prism.Core NuGetパッケージのPrism.Mvvm名前空間にあります。 ViewModelLocatorは、プラットフォーム固有のパッケージ（Prism.WPF、Prism.Forms）NuGetパッケージのPrism.Mvvm名前空間にあります。

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翻訳)
注意
Xamarin.Formsを使用して開発する場合、ViewModelLocatorは必須であり、INavigationServiceの正しいインスタンスをViewModelに提供する必要があるため、すべてのビューに自動的に適用されます。 Xamarin.Formsアプリを開発する場合、ViewModelLocatorはオプトアウトのみです。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/a42a01e6-7f48-eaaf-3e5d-479727307655.png)](https://www.youtube.com/watch?v=I_3LxBdvJi4)

###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翻訳)
アプリケーションがViewModelLocatorのデフォルトの命名規則に従っていない場合は、アプリケーションの要件を満たすように規則を変更できます。 ViewModelLocationProviderクラスは、ビューをビューモデルに関連付けるための独自の規則を提供するために使用できるSetDefaultViewTypeToViewModelTypeResolverと呼ばれる静的メソッドを提供します。

ViewModelLocatorの命名規則を変更するには、App.xaml.csクラスのConfigureViewModelLocatorメソッドをオーバーライドします。 次に、ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolverメソッドでカスタムの命名規則ロジックを提供します。

```
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/f42885fb-258e-cf86-200d-b5729d872d7b.png)
](https://www.youtube.com/watch?v=o4ibaOFvfww)

###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翻訳)
アプリがViewModelLocatorのデフォルトの命名規則に従っている場合がありますが、規則に従っていないViewModelがいくつかあります。 すべての命名要件を条件付きで満たすように命名規則ロジックをカスタマイズする代わりに、ViewModelLocationProvider.Registerメソッドを使用して、ViewModelLocatorで特定のビューへのViewModelのマッピングを直接登録できます。

次の例は、MainWindowというビューとCustomViewModelという名前のViewModelの間のマッピングを作成するさまざまな方法を示しています。
####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翻訳)
注意
ViewModelLocatorに直接ViewModelを登録する方が、デフォルトの命名規則に依存するよりも高速です。 これは、命名規則ではリフレクションを使用する必要があるためですが、カスタムマッピングでは、タイプがViewModelLocatorに直接提供されます。

IMPORTANT
The viewTypeName parameter must be the fully qualifyied name of the view's Type (Type.ToString()). Otherwise the mapping will fail.
(Google翻訳)
重要
viewTypeNameパラメータは、ビューのタイプの完全修飾名（Type.ToString（））である必要があります。 そうでない場合、マッピングは失敗します。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/0e20146d-0c72-2771-fcd1-6492ca2b5b09.png)
](https://www.youtube.com/watch?v=phMc4OuKs58)

###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翻訳)
デフォルトでは、ViewModelLocatorは、選択したDIコンテナを使用して、Prismアプリケーションを作成し、ViewModelを解決します。 ただし、ViewModelの解決方法をカスタマイズしたり、リゾルバーを完全に変更したりする必要がある場合は、ViewModelLocationProvider.SetDefaultViewModelFactoryメソッドを使用してこれを実現できます。

この例は、ViewModelインスタンスの解決に使用されるコンテナーを変更する方法を示しています。

```
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翻訳)
これは、ViewModelが作成されているビューのタイプを確認し、ViewModelの作成方法を制御するロジックを実行する方法の例です。

```
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);
    });
}
```