かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

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