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