WPF入门到跪下 第十一章 Prism(四)View与ViewModel的自动关联

news2025/1/9 15:31:20

View与ViewModel的自动关联

一、ViewModelLocator

在学习MvvmLight框架时,也使用了ViewModelLocator类。但在MvvmLight框架中,ViewModelLocator只是一个自定义类,与框架无关,目的就是初始化IOC容器。而在Prism框架中则不同,Prism框架内置了ViewModelLocator类,并且可以帮助我们进行ViewViewModel层之间的绑定。

1、使用示例

先查看一下整个使用过程,再进行解析。

程序集中,创建Views文件夹、ViewModels文件夹,将MainWindow.xaml放入Views文件夹中,并在ViewModels文件夹中创建MainWindowViewModel类

注意,在移动MainWindow.xaml时,切记要修改命名空间(xaml文件中的x:Class属性以及后台代码中的命名空间)

public class MainWindowViewModel:BindableBase
{
    private int value;

    public int Value
    {
        get { return value; }
        set
        {
            SetProperty(ref this.value, value);
        }
    }
}

在这里插入图片描述

在MainWindow.xaml中进行Prism命名空间的引入以及ViewModelLocator.AutoWireViewModel属性的设置

需要注意,AutoWireViewModel默认就是为True,表示自动关联ViewModel,因此这个命名空间引入以及设置属性的步骤是可以省略的。

  • 示例

    <Window ......
            xmlns:prism="http://prismlibrary.com/"
            prism:ViewModelLocator.AutoWireViewModel="True"
    				......>
        <Grid>
            <TextBlock Text="{Binding Value}"/>
        </Grid>
    </Window>
    

2、关联规则

通过**ViewModelLocator**进行View与ViewModel层的自动关联,有以下几点规则:

  • ViewModel(视图模型类)与View(视图类)位于同一个程序集中
  • 默认情况下,视图模型类位于.ViewModels命名空间下,视图类位于.Views命名空间下。可以理解为放置在项目目录的ViewModelsViews文件夹下。(试了一下,直接放在项目目录下或者ViewModelView文件夹下也是可以的)
  • 视图模型类与视图类名称对应,并以ViewModel结尾。这里有一点需要注意的,如果视图类的名称本身就是以View结尾的,例如StudentView,那么视图类名称中只要一个View就可以了,也就是StudentViewModel而不是StudentViewViewModel。

个人建议是,将视图模型类统一放在ViewModels文件夹中,视图类位于Views文件夹中,方便管理。

二、个性化配置

1、关联规则配置

这里以PrismApplication启动方式为例,在Prism框架中,会自动将View与ViewModel进行关联,其关联规则如上文所述。

默认关联过程大致如下:

  • 规定视图层的类型必须放在.Views命名控件的子空间下,然后将命名空间中的Views替换成ViewModels,来获得对应的视图模型的所在命名空间,例如Schuyler.Views -> Schuyler.ViewModels
  • 获得视图层的类类型后,检查类类型的全名是不是以View结尾,如果是则在尾部添加Model,否则则添加ViewModel,以此来获得视图层类类型所对应的视图模型层的类类型。
  • 通过视图层类类型命名空间获取到视图模型层的类类型后,将该视图模型层的实例对象设置为对应视图层实例对象的DataContext

根据上述关联过程,想要修改默认的关联规则,只需要在启动类(App)中,重写PrismApplication类的ConfigureViewModelLocator方法,并在方法中通过ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver方法来进行关联过程的修改即可。

ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(Func<Type, Type> viewTypeToViewModelTypeResolver):设置默认的视图类型与视图模型类型的分析器。

  • viewTypeToViewModelTypeResolver:接收一个Type类型参数,并返回一个Type类型的Func委托。接收的Type为视图类的类类型,而从哪个命名空间获取这个类类型应该是根据启动时设置的主窗口的所在命名空间来定下的。返回的Type则是根据接收到的Type参数的命名空间转化后获得的对应视图模型的类类型。

具体实现代码如下:

前提是使用PrismApplication进行项目启动,实现方式可以翻看前文。

这里是将ViewTest作为存放View类型的文件夹、ViewModelTest则是用来存放ViewModel类型的文件夹。

  • 示例

    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<ViewTest.MainWindow>();
        }
    
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            
        }
    
        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);
        }
    
    }
    

2、独立关联规则配置

上面所说得关联规则配置指的是整个项目内都必须遵守的,而有些时候只希望配置某对View与ViewModel的关联规则,比如View与ViewModel可能不再一个程序集、不在指定目录、类型名字不匹配等。

此时则需要重写PrismApplication类的ConfigureViewModelLocator方法,并在方法中通过调用ViewModelLocationProvider.Register方法来进行单独的配置,具体由如下四种配置方法:

  • 示例

    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            //创建主窗口对象
            return Container.Resolve<ViewTest.MainWindow>();
        }
    
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //这里进行IOC容器管理类型的注册
        }
    
        protected override void ConfigureViewModelLocator()
        {
            base.ConfigureViewModelLocator();
            //方式1:通过 类型名称/类型
            //ViewModelLocationProvider.Register(typeof(ViewTest.MainWindow).ToString(), typeof(ViewModelTest.MainViewModel));
            //方式2:通过 类型/工厂
            //ViewModelLocationProvider.Register(typeof(ViewTest.MainWindow).ToString(), 
            //    ()=>Container.Resolve<ViewModelTest.MainViewModel>());
            //方式3:通过 泛型/工厂
            //ViewModelLocationProvider.Register<ViewTest.MainWindow>(() => Container.Resolve<ViewModelTest.MainViewModel>());
            //方式4:通过 泛型
            ViewModelLocationProvider.Register<ViewTest.MainWindow, ViewModelTest.MainViewModel>();
        }
    }
    

设计时的DataContext设置

无依赖注入

DataContext一般是在程序运行时进行关联的如果希望在进行视图设计时就可以将数据展示出来方便进行图形设计,可以通过<d:Window.DataContext>进行设置

  • 示例

    public class MainWindowViewModel
    {
    
        public string TestData { get; set; } = "测试数据";
    }
    
    <Window x:Class="WpfApp1.Views.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            xmlns:viewModels ="clr-namespace:WpfApp1.ViewModels"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <d:Window.DataContext>
            <viewModels:MainWindowViewModel/>
        </d:Window.DataContext>
        <Grid>
            <TextBlock Text="{Binding TestData}"/>
        </Grid>
    </Window>
    

有依赖注入

在使用Prism框架下,视图模型很多时候都会通过IOC容器,在构造函数中注入对应的服务,这个时候要在视图中设置设计时的DataContext,就需要借助ObjectDataProvider

  • 示例

    public class MainWindowViewModel
    {
        private IRegionManager _regionManager = null!;
        
        public MainWindowViewModel(IRegionManager regionManager)
        {
            _regionManager = regionManager;
        }
        
        ......
    }
    
    <Window ......
            xmlns:prism="http://prismlibrary.com/"
            ......>
        <d:Window.DataContext>
            <ObjectDataProvider ObjectType="local:MainWindowViewModel">
                <ObjectDataProvider.ConstructorParameters>
                    <prism:RegionManager/>
                </ObjectDataProvider.ConstructorParameters>
            </ObjectDataProvider>
        </d:Window.DataContext>
        ......
    </Window>
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2112859.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

matplotlib中文乱码问题

在使用Matplotlib进行数据可视化的过程中&#xff0c;经常会遇到中文乱码的问题。显示乱码是由于编码问题导致的&#xff0c;而matplotlib 默认使用ASCII 编码&#xff0c;但是当使用pyplot时&#xff0c;是支持unicode编码的&#xff0c;只是默认字体是英文字体&#xff0c;导…

【LeetCode】08.字符串转换整数

题目要求 解题思路 本题没有难点&#xff0c;只需注意最大整数的比较时要切换成long long 代码实现 class Solution { public:int myAtoi(string s) {//标记正负号int flag1;long long ret0;int ns.size();int i0;//去除空格while(s[i] ) i;//识别符号if(s[i]-) flag-1;i…

vue项目打包后,生成的index.html直接本地打开后没内容

应该是文件路径找不到了 可以打开控制台看看 可以看到加载css&#xff0c;js&#xff0c;图标资源失败&#xff0c;所以是文件路径问题 vue-cli工程化生成的项目在打包后&#xff0c;默认的资源寻找路径是根&#xff0c;所以可以看到它直接在/F;/favicon找图标&#xff0c;但…

机器学习模型中的因果关系:引入单调约束

单调约束是使机器学习模型可行的关键&#xff0c;但它们仍未被广泛使用欢迎来到雲闪世界。 碳ausality 正在迅速成为每个数据科学家工具包中必不可少的组成部分。 这是有充分理由的。 事实上&#xff0c;因果模型在商业中具有很高的价值&#xff0c;因为它们为“假设”情景提…

经典文献阅读之--WidthFormer(基于Transformer的BEV方案量产方案)

0. 简介 《WidthFormer: Toward Efficient Transformer-based BEV View Transformation》提出了WidthFormer&#xff0c;这是一种基于Transformer的新颖鸟瞰视角&#xff08;Birds-Eye-View, BEV&#xff09;三维检测方法&#xff0c;专为实时自动驾驶应用而设计。WidthFormer…

网络安全 day5 --- 反弹SHELL不回显带外正反向连接防火墙出入站文件下载

免责声明 本免责声明适用于作者所有文章内容。使用者需明确&#xff0c;网络安全技术仅供学习和合法研究使用&#xff0c;不得用于任何非法活动&#xff0c;如未经授权的入侵、攻击或数据窃取&#xff0c;所有相关法律责任由使用者自行承担。由于网络安全操作可能带来系统崩溃、…

程序中的零值比较

前言&#xff1a;什么是零值&#xff1f; 在C/C中&#xff0c;“零值”通常指的是数值类型的零&#xff08;0&#xff09;&#xff0c;对于指针来说则是空指针&#xff08;nullptr 或 NULL&#xff09;。下面我们将分别讨论如何比较整型、字符、浮点数和指针与“零值”的比较。…

顺序表与链表练习

目录 1.在长度为n(n > 1)的单链表上&#xff0c;设有头和尾两个引用&#xff0c;执行( )操作与链表的长度有关。 2.下列关于链表的说法那个是正确的( ) 3. 关于链表和顺序表间的区别&#xff0c;叙述错误的是&#xff08; &#xff09; 4.在长度为 n 的顺序表下标为 i…

oatpp apiclient 客户端get,post请求python fastapi demo

最新用fastapi搞了个服务端,python功能太强了,就是环境不好弄,弄好后,不要轻易换python版本,不要装多个python版本 前面搞了个oatpp webapi服务端,现在要用客户端,为什么用opatpp客户端,因为他不再带其他库了 demo: 我的请求比较简单,就是向python 的 fastapi服务端…

CSP-J基础之常见的竞赛题库

文章目录 CSP-J基础之常见的竞赛题库1. 可达 (KEDA)2. 洛谷 (Luogu)3. Codeforces 洛谷账号的注册总结 CSP-J基础之常见的竞赛题库 在备战CSP-J&#xff08;Certified Software Professional Junior&#xff09;及其他信息学竞赛时&#xff0c;选手们常需要借助在线题库来进行…

GIS圈大事件!Cesium被收购了,是好是坏?

大家好&#xff0c;我是日拱一卒的攻城师不浪&#xff0c;致力于技术与艺术的融合。这是2024年输出的第34/100篇文章。 Cesium开发交流群V&#xff1a;brown_7778&#xff08;备注来意&#xff09; 一觉醒来&#xff0c;突然看到Cesium官方发的消息&#xff0c;宣布通过收购的方…

第十三届山东省ICPC

vp链接&#xff1a;https://codeforces.com/gym/104417 A. Orders 根据题意模拟&#xff0c;分别按照 a&#xff0c;b 排序&#xff0c;排序后再判断该订单是否能完成。 #include <bits/stdc.h> using namespace std;#define int long longconst int N 105; int n, k…

C#索引器(Indexer)

索引器(Indexer)允许一个对象可以像数组一样使用下标的方式来访问. 当为类定义一个索引器时,该类的行为就会像一个虚拟数组(virtual array) 一样.可以使用数组访问运算符[]来访问该类的成员. 语法 一维索引器的语法如下: element-type this[int index] { // get 访问器 …

Minimax-秋招正式批-面经(SQL相关)

1. 谈谈对聚簇索引的理解 聚簇索引 InnoDB通过主键聚集数据&#xff0c;如果没有定义主键&#xff0c;InnoDB会选择非空的唯一索引代替。如果没有这样的索引&#xff0c;InnoDB会隐式定义一个主键来作为聚簇索引聚簇索引就是按照每张表的主键构造一颗B树&#xff0c;同时叶子…

中国书法——孙溟㠭浅析碑帖《越州石氏帖》

孙溟㠭浅析碑帖《越州石氏帖》 《越州石氏帖》 是一部汇集多本摹刻的帖&#xff0c;南宋时期的会稽石邦哲&#xff08;字熙明&#xff09;把家藏的一些法书碑帖集中一起摹刻成的&#xff0c;宋理宗时临安书商陈思《宝刻丛编》有记載这部帖的目录。现在还存有宋代时拓的残缺本…

golang hertz框架入门

两种模式新建项目 1、手动新建项目 2、使用hz工具新建项目 一、手动创建项目&#xff0c;并拉取框架 1、新建项目目录 hertz_demo_w 2、在项目跟目录新建main.go 文件 package mainimport ("context""github.com/cloudwego/hertz/pkg/app""github.…

WPS如何查看已添加到词典的单词

WPS Office&#xff08;12.1.0.17827&#xff09; ① 点击文件&#xff0c;在文件中找到选项 ② 找到拼写检查并点击自定义词典 ③ 如果要删除已添加到词典的"错词"&#xff0c;则点击修改 ④ 选择"错词", 点击删除

电工基础知识

1、电工常用的电工工具 2、PPR常用配件名称 3、铜芯导线如何选择线鼻子 4、丝锥孔径对照表 5、三相电机接线方法_星形_角型 6、内六角螺铨尺寸表 7、常用螺母规格尺寸 8、常用螺栓螺母名称 9、灭火器分类使用 10、电缆颜色使用代码 11、电缆铜铝鼻子 12、空气开关

力扣第一题:两数之和

文章目录 需求分析代码结尾 需求 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素。 你…

Hexo博客构建记录

开学了&#xff0c;准备让休息了两个月的大脑重新活动一下筋骨&#xff0c;就尝试了一下Hexo博客的简单构建。在这里记录一下&#xff0c;方便以后使用。 以下是笔者搭建时用到的教程 简单搭建教程 简单&#xff0c;虽然个人感觉布局有点乱&#xff0c;关于上传文章的介绍略…