かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Xamarin版PrismでViewとViewModelの紐づけルールを変える

PrismはデフォルトでViews名前空間にあるViewとViewModels名前空間にあるViewModelを紐づける機能を持っています。この機能を有効化するには、PageのXAMLに以下の2行を追加します。

xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"

ということで、Viewに対して属性でViewModelの型を指定するようにしてみたいと思います。これでViewに対して任意のViewModelを紐づけることができます。

まず、ViewModelを指定するための属性を定義します。

public class ViewModelAttribute : Attribute
{
    public Type ViewModelType { get; }

    public ViewModelAttribute(Type viewModelType)
    {
        this.ViewModelType = viewModelType;
    }
}

そして、AppクラスのConfigureViewModelLocatorをオーバーライドして以下のようなに記述します。

protected override void ConfigureViewModelLocator()
{
    base.ConfigureViewModelLocator();
    ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(viewType =>
    {
        var vm = viewType.GetTypeInfo().GetCustomAttribute<ViewModelAttribute>();
        return vm?.ViewModelType;
    });
}

ViewとViewModelの紐づけルールはViewModelLocationProviderのSetDefaultViewTypeToViewModelTypeResolverでラムダ式で指定します。ここでは、属性をとってきて、そのViewModelTypeで指定された型を返しています。

あとは、View側に以下のような感じでViewModelの型を指定すればOKです。

[ViewModel(typeof(MainPageViewModel))]
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }
}