8-10 ViewModelLocator Prism官网案例学习
声明
原文出处如下:
这是一篇记录作者学习Prism的随笔,该随笔的内容是作者通过5个资源学习汇总而成,主要是为了方便自己以后拾遗温习所用,如果文中内容看不懂,推荐直接阅读相关原文。
09-10 ViewModelLocator
使用ViewModelLocator
所述ViewModelLocator
用于接线DataContext
的图,以使用标准命名约定的一个ViewModel的实例。
Prism ViewModelLocator
具有一个AutoWireViewModel
附加属性,该属性设置为时,将true
调用类中的AutoWireViewModelChanged
方法ViewModelLocationProvider
来解析视图的ViewModel,然后将视图的数据上下文设置为该ViewModel的实例。
将AutoWireViewModel
附加的属性添加到每个视图:
<Window x:Class="Demo.Views.MainWindow"
...
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
为了找到ViewModel,第ViewModelLocationProvider
一次尝试从该ViewModelLocationProvider.Register
方法可能已经注册的任何映射中解析ViewModel (请参阅Custom ViewModel Registrations)。如果无法使用此方法解析ViewModel,则ViewModelLocationProvider
退回到基于约定的方法来解析正确的ViewModel类型。
该约定假定:
- ViewModel与视图类型在同一程序集中
- ViewModels在
.ViewModels
子命名空间中 - 视图位于
.Views
子命名空间中 - ViewModel名称与视图名称相对应,并以“ ViewModel”结尾。
更改ViewModelLocator命名约定
官方案例
如果您的应用程序不遵循ViewModelLocator
默认的命名约定,则可以更改约定以满足应用程序的要求。本ViewModelLocationProvider
类提供了一个称为静态方法SetDefaultViewTypeToViewModelTypeResolver
,可以用来提供自己的约定关联视图视图模型。
若要更改ViewModelLocator
命名约定,请重写类中的ConfigureViewModelLocator
方法App.xaml.cs
。然后在该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);
});
}
博客案例
约定就是要来被打破的,有人可能觉得后缀加一个ViewModel实在是LowB,我想改变他,可以不可以?当然阔以啦。
prism为我们提供了一个可重写的ConfigureViewModelLocator的方法来配置ViewModel的定位器,如果你想修改默认的约定为View的名字后面+VM,你可以在app.xaml.cs
这样写:
protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
{
var viewName = viewType.FullName;
var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
var viewModelName = $"{viewName}VM, {viewAssemblyName}";
return Type.GetType(viewModelName);
});
}
手动注册特定视图的ViewModel
官方介绍
在某些情况下,您的应用遵循ViewModelLocator
默认的命名约定,但是您有许多不遵循约定的ViewModel。无需尝试自定义命名约定逻辑以有条件地满足您的所有命名要求,您可以ViewModelLocator
使用ViewModelLocationProvider.Register
方法直接使用来注册ViewModel到特定视图的映射。
以下示例说明了在称为的视图MainWindow
和名为的ViewModel 之间创建映射的各种方法CustomViewModel
。
类型/类型
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>();
注意
与ViewModelLocator
相比,直接注册ViewModels 比依赖默认命名约定要快。这是因为命名约定需要使用反射,而自定义映射将类型直接提供给ViewModelLocator
。
重要
该viewTypeName
参数必须是视图的Type的全qualifyied名(Type.ToString()
)。否则,映射将失败。
博客案例
这世界上不乏个性鲜明的人,你们那些约定和打破的约定还不都是一路货色。我就要不一样的,我想跟谁绑在一起就跟谁绑在一起。好,你跟谁好是你的自由,Prism不能限制你,不然你会投诉它不民主。😂
如果你想指定你绑定的ViewModel对象又不想遵循一定的规则,你同样可以在ConfigureViewModelLocator方法中注册绑定,像下面这样:
protected override void ConfigureViewModelLocator()
{
base.ConfigureViewModelLocator();
// 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>();
}
当然了,在xaml中的
prism:ViewModelLocator.AutoWireViewModel="True"
依旧是必不可少的。