说一下我对Mvvm模式的理解

本文详细探讨了WPF项目中使用Mvvm模式的实践,包括模式的起源、主流框架应用、思想分析、常见误区及个人经验分享。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用WPF+Mvvm开发一年多,期间由于对Mvvm模式的理解不足,遇到了很多问题,也绕了很多弯子;网上提供的Mvvm的示例比较简单,实际项目中的需求也各种各样。
不过经过几个项目,也有了一些对Mvvm模式的理解:

1. Mvvm是什么,Mvvm是怎么来的?
Mvvm模式广泛应用在WPF项目开发中,使用此模式可以把UI和业务逻辑分离开,使UI设计人员和业务逻辑人员能够分工明确。

Mvvm模式是根据MVP模式来的,可以简单的说,Mvvm模式就是WPF版的MVP模式。MVP模式,MVC模式,这几个模式都是为了抽离出UI逻辑和业务逻辑。



2. 使用Mvvm模式可以参考的主流框架及简单介绍。
主流开源框架:Simple Mvvm,Mvvm Light和Prism。
Simple Mvvm和Mvvm Light基本一致,都是对Mvvm模式的基础封装,并加入了一些不错的功能,消息传输机制,依赖注入等等。开发中小项目推荐使用这两个的其中一个。
Prism是微软给出的一个Mvvm框架,不过它的关注点不仅仅是Mvvm模式,我觉得主要是模块的思想更多一些。大项目的话才推荐使用这个框架,比如一个系统需要分为N个团队进行不同模块的开发,然后再组织成一个系统。

3. 使用Mvvm模式的思想分析问题。
现在有一个功能:用户填入姓名,年龄,选择最喜欢的颜色,然后点击确定按钮提交。就是这样简单的一个调查表。
a.首先设计UI,UI看起来可能是这样的:


b.根据UI去设计对应的ViewModel层需要那些属性,数据和命令:

 Name:string
 Age:int
 FavoriteColor:string
 Submit:Command


c.在ViewModel层的SubmitCommand命令中,调用Model层的Submit方法进行逻辑处理。Model层看起来可能是这样的:

 public string Name { get; set; }
 public int Age { get; set; }
 public string FavoriteColor { get; set; }
 public void Submit() { ... }


4. 看到的一些对Mvvm模式的看法,觉得不太正确。
a.Code-Behind文件要保证绝对干净。
这个说法有些太绝对了,理想状态下,View层的Code-Behind文件中只有在构造函数中调用初始UI元素的一行代码及设置View层的DataContext为对于的ViewModel层。
其实,Code-Behind中还可以些一些UI的逻辑的,比如一些丰富的动画效果,或者直接设置某个元素的样式等。
不过,Code-Behind中确实是不可以写业务逻辑的。
b.ViewModel层不能是Model层的简单封装,ViewModel层也不能是View层的简单映射。ViewModel层和View层要绝对分离,ViewModel层要和View层一样去面向需求设计。
我觉得这样做有点太过了。
Mvvm的目的只是为了UI逻辑和业务逻辑的分离,你说业务逻辑和数据要写在哪一层呢?没错,Model层。
ViewModel层的主要责任是表现逻辑和状态,即ViewModel层是连接View层和Model层的。Model层的一些业务逻辑的状态是需要通过ViewModel层暴露给View层来反映给软件使用者的。

5.我对WPF+Mvvm模式开发的一些经验。
a.WPF的几个重要概念要熟练理解和运用:模板,依赖属性,数据绑定。和Mvvm模式的结合使用,能发挥出很好的效果。
b.团队中的成员最好能够对Mvvm模式有统一的理解和认识。
c.Mvvm模式只是一个模式而已,不是有了Mvvm模式就能写出优美的代码,涉及到具体的业务逻辑,还是需要你以及你的团队有足够强的设计能力。

各位大牛如有不同的观点可以一起讨论下。

### MVVM模式概念 MVVM(Model-View-ViewModel)是一种软件架构模式,主要用于构建用户界面。它最早由微软在2005年推出并应用于WPF框架中[^2]。MVVM的设计理念源自经典的MVC模式,但在功能划分上更加专注于数据绑定和逻辑分离。 #### 核心组件 1. **Model**: 表示应用程序中的数据模型以及业务逻辑部分。它是独立于视图的存在,并不关心如何展示数据。 2. **View**: 负责呈现用户界面的部分。它的职责仅限于显示来自`ViewModel`的数据并与之交互。 3. **ViewModel**: 这是MVVM的关键所在。它充当了连接`View`和`Model`的桥梁角色。一方面向`View`提供可观察的数据源以便实现双向绑定;另一方面通过接口或者服务与`Model`通信获取实际所需的信息[^1]。 ### 实现机制 为了更好地理解MVVM的实际应用, 下面以一个简单的例子明其工作流程: 假设我们有一个待办事项列表(Todo List),其中包含添加新任务的功能: ```javascript // 定义 Model 部分 class TodoModel { constructor() { this.todos = []; } addTodo(todoText) { const newId = this.todos.length + 1; this.todos.push({ id: newId, text: todoText }); } } // 创建 ViewModel 来管理状态变化 const viewModel = new Vue({ el: '#app', data: { todos: [], newTodoText: '' }, methods: { addNewTodo() { if (this.newTodoText.trim()) { // 确保输入不是空白字符 model.addTodo(this.newTodoText); // 更新model this.todos = [...model.todos]; // 同步到viewModel this.newTodoText = ''; // 清空输入框 } } } }); // 初始化 Model 并填充一些初始数据 let model = new TodoModel(); model.addTodo('学习JavaScript'); model.addTodo('练习Vue.js'); // 将初始数据同步至 ViewModel viewModel.todos = [...model.todos]; ``` 在这个案例里,当用户提交一个新的todo项时,会触发 `addNewTodo()` 方法。此方法不仅修改了本地存储(`data`)里的副本还调用了真正的后台操作即更新原始model实例的内容。由于采用了响应式的编程风格(Vue内置特性), 所有依赖这些变量的地方都会自动重新渲染出来而无需手动干预DOM节点的操作过程[^1]。 另外值得注意的是,在某些平台比如Android开发环境下还可以利用Data Binding Library进一步简化上述代码结构从而减少样板代码量同时增强程序健壮性和维护便利度等问题[^3]。 ### 数据流方向 在一个典型的MVVM系统里面存在两种主要的数据流动形式: - **单向数据流**:从`ViewModel`流向`View`, 当前者的属性发生变化之后后者能够立刻反映出最新的改变情况; - **双向数据绑定**:允许开发者既可以从控件读取当前值也可以反过来设置它们的新数值进而影响对应的字段内容。这种技术特别适合表单验证场景下的即时反馈需求等等[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值