WPF-Prism中View和ViewModel的关联
在MainWindow.xaml中进行Prism命名空间的引入以及ViewModelLocator.AutoWireViewModel属性的设置
需要注意,AutoWireViewModel默认就是为True,表示自动关联ViewModel,因此这个命名空间引入以及设置属性的步骤是可以省略的
2、通过ViewModelLocator进行View与ViewModel层的自动关联,有以下几点规则:
ViewModel与视图类型位于同一个程序集中
ViewModel位于.ViewModels子命名空间中,测试后发现其实.ViewModel子命名空间中也可以。
View位于.Views子命名空间中,测试后发现其实.View子命名空间中也可以。
ViewModel名称与视图名称对应,以ViewModel结尾。这里有一点需要注意的,如果视图的名称本身就是以View结尾的,例如StudentView,那么ViewModel名称中只要一个View就可以了,也就是StudentViewModel。
3、
这里以PrismApplication启动方式为例,在Prism框架中,会自动将View与ViewModel进行关联,其关联规则如上文所述。
默认关联过程大致如下:
规定视图层的类型必须放在.Views命名控件的子空间下,然后将命名空间中的Views替换成ViewModels,来获得对应的视图模型的所在命名空间,例如Schuyler.Views -> Schuyler.ViewModels
获得视图层的类类型后,检查类类型的全名是不是以View结尾,如果是则在尾部添加Model,否则则添加ViewModel,以此来获得视图层类类型所对应的视图模型层的类类型。
通过视图层类类型命名空间获取到视图模型层的类类型后,将该视图模型层的实例对象设置为对应视图层实例对象的DataContext。
根据上述关联过程,想要修改默认的关联规则,只需要在启动类(App)中,重写PrismApplication类的ConfigureViewModelLocator方法,并在方法中通过ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver方法来进行关联过程的修改即可。
代码如下两种:
protected override void ConfigureViewModelLocator() { base.ConfigureViewModelLocator(); ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(ViewTypeToViewModelTypeResolver); } private Type ViewTypeToViewModelTypeResolver(Type viewType) { var viewName = viewType.FullName; //获得视图模型的命名空间 var viewModelName = viewName.Replace(".ViewTest.", ".ViewModelTest."); //判断视图类是不是以Window结尾,是则去掉 if (viewModelName.EndsWith("Window")) { viewModelName = viewModelName.Substring(0, viewModelName.Length - 6); } //判断是不是以View结尾 if (viewModelName.EndsWith("View")) { viewModelName += "Model"; } else { viewModelName += "ViewModel"; } return Type.GetType(viewModelName); }
或
protected override void ConfigureViewModelLocator() { ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) => { var viewName = viewType.Name; var viewModelNameSpace = $"WpfApp5.ViewModel";//名称控件位置 var viewModelName = $"{viewModelNameSpace}.{viewName}VM";//ViewModel的位置 全名称空间 //如不是同一个项目文件中,ViewModel是被分开在另一个项目文件中 那么需要将读取ViewModel项目文件下的dll //var assembly = Assembly.LoadFile(Path.Combine(Directory.GetCurrentDirectory(), "Paramecium.App.ViewModels.dll")); Type type = Type.GetType(viewModelName); return type; }); }
总结下一共有下面几种:
在Prism框架中,查找对应的ViewModel主要依赖于以下几种方式:
-
自动连线:Prism框架通过命名约定自动将View与ViewModel关联起来。例如,如果有一个名为"MainView"的View类,那么Prism会尝试找到一个名为"MainViewModel"的ViewModel类,并将它们自动关联起来。这种自动连线是通过在View的XAML文件中添加
:ml-search[prism:ViewModelLocator.AutoWireViewModel="True"
属性实现的12。 -
手动关联:除了自动连线外,还可以手动在代码中关联View和ViewModel。例如,在View的代码后置文件中(如
MainView.xaml.cs
),可以通过设置DataContext
属性来手动创建并关联ViewModel。这种方式需要开发者显式地将ViewModel实例分配给View的DataContext
属性1。 -
使用注入容器:Prism框架提供了依赖注入容器,允许通过容器自动创建并关联View和ViewModel。这需要在App的初始化过程中注册View和ViewModel的映射关系。通过
IContainerRegistry
接口的Register
方法,可以将View和ViewModel的实例注册到容器中,从而在需要时由容器提供相应的实例13。 -
自定义命名约定和ViewModelLocator:如果默认的命名约定不满足需求,可以通过实现自定义的ViewModelLocator或者更改默认的命名约定来满足特定的项目结构。这涉及到对
:ml-search[ViewModelLocationProvider]
类的使用,允许开发者提供自己的逻辑来确定如何根据View的类型找到对应的ViewModel类型4。这种是处理类似view和ViewModel不在同一个项目中的。
综上所述,Prism框架提供了多种方式来查找和关联View与ViewModel,从自动根据命名约定进行关联,到手动在代码中设置,再到使用依赖注入容器进行自动管理,以及允许开发者自定义查找逻辑,以满足不同项目的需求。