Prism 6.ViewModel定位器

Prism 6.ViewModel定位器

ViewModel定位器用一个标准的命名约定来给View的DataContext一个ViewModel实例

ViewModel有一个AutoWireViewModel的附加属性,当设置为true就会在ViewModel中调用AutoWireViewModelChanged方法去给View解析ViewModel,然后给View的数据上下文设置一个ViewModel的实例。

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

定位器首先会尝试解析被ViewModelLocationProvider.Register注册的映射表,如果没有,那么定位器会尝试一下规则

1 ViewModel和View在同一个程序集

2 ViewModel在以.ViewModel的子命名空间中

3 View在以.View的子命名空间中

4 View和ViewModel命名相同

改变命名约定

如果你不想使用默认的命名约定,你可以是用你自己的命名规则,ViewModelLocationProvider提供了方法可以使你定义自己的约定来连接View和ViewModel

你需要在App.xaml.cs里面重写ConfigureViewModelLocator方法,然后在ViewModelLocationProvider.Register使用你自己的命名规则

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

自定义ViewModel注册

如果出现这样的情景:一部分View/ViewModel使用默认的命名约定,一部分View/ViewModel使用自定义的约定,你可以不用费劲去定义自己的命名约定,可以直接使用ViewModelLocationProvider.Register的方法去给一些特殊的View注册ViewModel

以下提供了几种方式:

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

如何控制ViewMdel的解析

默认的,ViewModelLocator是使用你在创建应用时所选择的DI容器来解析ViewModel的。

你也可以通过使用ViewModelLocationProvider.SetDefaultViewModelFactory的方法来自定义如何解析ViewModel

例子:

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

    ViewModelLocationProvider.SetDefaultViewModelFactory(viewModelType) =>
    {
        return MyAwesomeNewContainer.Resolve(viewModelType);
    });
}
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);
    });
}
原文地址:https://www.cnblogs.com/swobble/p/12809984.html