WPF-Prism中View和ViewModel的关联

1、

在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主要依赖于以下几种方式:

  1. ‌自动连线‌:Prism框架通过命名约定自动将View与ViewModel关联起来。例如,如果有一个名为"MainView"的View类,那么Prism会尝试找到一个名为"MainViewModel"的ViewModel类,并将它们自动关联起来。这种自动连线是通过在View的XAML文件中添加:ml-search[prism:ViewModelLocator.AutoWireViewModel="True"属性实现的‌12。

  2. ‌手动关联‌:除了自动连线外,还可以手动在代码中关联View和ViewModel。例如,在View的代码后置文件中(如MainView.xaml.cs),可以通过设置DataContext属性来手动创建并关联ViewModel。这种方式需要开发者显式地将ViewModel实例分配给View的DataContext属性‌1。

  3. ‌使用注入容器‌:Prism框架提供了依赖注入容器,允许通过容器自动创建并关联View和ViewModel。这需要在App的初始化过程中注册View和ViewModel的映射关系。通过IContainerRegistry接口的Register方法,可以将View和ViewModel的实例注册到容器中,从而在需要时由容器提供相应的实例‌13。

  4. ‌自定义命名约定和ViewModelLocator‌:如果默认的命名约定不满足需求,可以通过实现自定义的ViewModelLocator或者更改默认的命名约定来满足特定的项目结构。这涉及到对:ml-search[ViewModelLocationProvider]类的使用,允许开发者提供自己的逻辑来确定如何根据View的类型找到对应的ViewModel类型‌4。这种是处理类似view和ViewModel不在同一个项目中的。

综上所述,Prism框架提供了多种方式来查找和关联View与ViewModel,从自动根据命名约定进行关联,到手动在代码中设置,再到使用依赖注入容器进行自动管理,以及允许开发者自定义查找逻辑,以满足不同项目的需求。

posted @ 2024-08-30 16:24  卡萨丁·周  阅读(97)  评论(0编辑  收藏  举报