当前位置: 首页 > news >正文

用MVVM设计模式提升WPF开发体验:分层架构与绑定实例解析

MVVM(Model-View-ViewModel)是一种架构模式,广泛应用于现代前端开发,尤其是在微软的WPF(Windows Presentation Foundation)应用程序中。它旨在通过将视图(UI)与业务逻辑(模型)分离,达到更高的代码可维护性和可测试性。MVVM 在 Microsoft 的推行下,成为 WPF 应用开发的标准设计模式之一。

一、历史背景

在 GUI 应用开发中,代码的复杂性主要来源于 UI 和业务逻辑的耦合。传统的MVC(Model-View-Controller)架构尝试解决这一问题,通过分离模型和视图,开发者可以更轻松地管理代码。MVVM 是对MVC 的改进,提出了视图模型(ViewModel)的概念,将视图与模型连接起来,极大地提升了数据绑定和双向数据更新的便捷性和灵活性。

MVVM 模式主要借助于 WPF 的数据绑定、命令和属性更改通知来实现,使得开发者可以将数据流的处理逻辑放入 ViewModel中,做到视图和数据逻辑的完全分离。

二、MVVM 模式的组成

Model:代表数据结构和业务逻辑,包含数据实体、数据访问层和业务规则的实现。它与视图无关,专注于应用程序的核心数据。
View:表示用户界面,是应用程序的可视化部分。它通过绑定从
ViewModel 获取数据,不直接处理数据逻辑。

ViewModel:充当 View 与 Model 的桥梁,包含 UI 逻辑和 Model 数据的映射逻辑。ViewModel 通过属性绑定和命令,向视图提供数据,并响应用户操作。

三、WPF 和 MVVM 的结合

WPF 为 MVVM 提供了强大的支持,其中数据绑定和命令是关键功能。WPF 的数据绑定可以通过简单的绑定语法,将 ViewModel 的数据呈现到视图中,而 WPF 的命令机制可以将用户的操作与 ViewModel 中的方法关联起来。

1. 数据绑定

数据绑定是 WPF 中的重要功能,它使得 ViewModel 的属性可以直接绑定到视图中的控件上。例如,通过绑定一个属性,TextBox 控件的内容可以实时更新到 ViewModel 的数据。

2. 命令

WPF 命令提供了一种方法,可以将按钮等控件的交互行为与 ViewModel 中的操作逻辑连接起来。通过 ICommand 接口,命令可以定义在 ViewModel 中并直接绑定到视图控件。

四、MVVM 应用实例:创建一个简单的 WPF 应用程序

以下将从零开始创建一个简单的 MVVM 应用,展示基本的 MVVM 模式实现。

4.1第一步:创建 WPF 项目

  1. 打开 Visual Studio,新建一个 WPF 应用程序项目。
  2. 命名项目,例如 MVVMExample。

项目创建成功后,会生成 MainWindow.xaml,我们将这个文件作为 View 视图部分。

4.2 第二步:创建 Model

在项目中添加一个 Models 文件夹,并创建一个数据类 Person.cs:

// Models/Person.cs
// 创建 Modelpublic class Person{public string FirstName { get; set; }public string LastName { get; set; }}

此 Person 类表示应用程序的数据结构。

4.3 第三步:创建 ViewModel

在项目中添加一个 ViewModels 文件夹,并创建 MainViewModel.cs,负责处理 Person 数据并提供给视图。

// ViewModels/MainViewModel.cs
using System.ComponentModel;
using MVVMExample.Models;namespace MVVMExample.ViewModels
{// 定义 ViewModel,充当视图和数据模型之间的中介。public class MainViewModel : INotifyPropertyChanged // 数据绑定中常用的接口,它允许对象通知其属性发生了变化。{// 定义字段 _personprivate Person _person;public Person Person{get => _person;set{_person = value;OnPropertyChanged(nameof(Person));}}// 实现构造方法public MainViewModel(){Person = new Person(){FirstName = "John",LastName = "Doe"};}public event PropertyChangedEventHandler? PropertyChanged;protected void OnPropertyChanged(string propertyName){//调用 PropertyChanged 事件的订阅者(通常是 UI 控件)进行更新。当 PropertyChanged 事件被触发时,//它会传递一个 PropertyChangedEventArgs 对象,该对象包含属性名 propertyName。?. 是空值检查操作符,确保在没有订阅者的情况下不会抛出异常。PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}

该 ViewModel 实现了 INotifyPropertyChanged 接口,允许通知视图属性更改。MainViewModel 类在初始化时创建了一个 Person 对象。

4.4 第四步:创建 View

回到 MainWindow.xaml,我们将添加 XAML 代码来展示 Person 的信息。

<!-- MainWindow.xaml -->
<Window x:Class="WpfApp1.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"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><!--创建View--><!--通过设置 DataContext,我们可以将视图模型(MainViewModel)绑定到当前窗口。所有在视图中使用数据绑定的元素都会通过这个数据上下文来获取数据。--><Window.DataContext><!--创建一个 MainViewModel 的实例,并将它作为数据上下文绑定到窗口。这意味着窗口中的所有数据绑定都会访问 MainViewModel 中的属性和数据。--><local:MainViewModel /></Window.DataContext><StackPanel><!--通过绑定,TextBox 的文本将与 MainViewModel 中的 Person.FirstName 属性保持同步。--><!--UpdateSourceTrigger=PropertyChanged这个属性告诉 WPF,当用户在文本框中修改文本时,立即将修改的值更新到 Person.FirstName 属性。这意味着属性会实时更新,而不仅仅是当控件失去焦点时才更新。--><TextBox Text="{Binding Person.FirstName,UpdateSourceTrigger=PropertyChanged}" Margin="10" /><TextBox Text="{Binding Person.LastName,UpdateSourceTrigger=PropertyChanged}" Margin="10" /><TextBlock Text="{Binding Person.FirstName}" Margin="10" FontSize="16" /><TextBlock Text="{Binding Person.LastName}" Margin="10" FontSize="16" /></StackPanel>
</Window>

此 XAML 文件展示了一个简单的 UI,包含两个 TextBox 和两个 TextBlock。TextBox 控件绑定到 Person.FirstName 和 Person.LastName 属性,允许用户输入姓名和姓氏。绑定的 UpdateSourceTrigger=PropertyChanged 确保属性值在更改时立即更新。

4.5 第五步:测试应用程序

启动应用程序,您会看到两个可编辑的文本框和两个文本块。编辑 TextBox 内容时,TextBlock 内容会即时更新,验证了数据绑定和 ViewModel 的有效性。
在这里插入图片描述

五、总结

使用 MVVM 模式可以清晰地分离视图和数据逻辑,特别是在大型应用程序中更为显著。在 MVVM 中:

View 负责 UI,展示数据;
ViewModel 负责处理 UI 与数据之间的绑定,管理业务逻辑;
Model 负责数据层,保持核心数据和规则。

通过这种结构化的方式,WPF 中的开发者可以构建更高效的、易维护的应用。

相关文章:

用MVVM设计模式提升WPF开发体验:分层架构与绑定实例解析

MVVM&#xff08;Model-View-ViewModel&#xff09;是一种架构模式&#xff0c;广泛应用于现代前端开发&#xff0c;尤其是在微软的WPF&#xff08;Windows Presentation Foundation&#xff09;应用程序中。它旨在通过将视图&#xff08;UI&#xff09;与业务逻辑&#xff08;…...

C++中的动态断言和静态断言

C中包含动态断言&#xff08;assert&#xff09;和静态断言&#xff08;static_assert&#xff09;&#xff0c;下面分别分析各自的用法。 1.动态断言&#xff08;assert&#xff09; assert 是一个宏&#xff0c;在预处理阶段不生效&#xff0c;在运行阶段才起作用&#xff0…...

运算放大器的学习(一)输入阻抗

输入阻抗 最近需要对运算放大器进行学习&#xff0c;我们后面逐一对其参数进行了解。 首先了解下输入阻抗。 放大电路技术指标测试示意图&#xff1a; 输入电阻&#xff1a; 从放大电路的输入端看进去的等效电阻称为放大电路的输入电阻&#xff0c;如上图&#xff0c;此处考虑…...

Rust枚举之卧龙凤雏(Rust Option枚举、Rust Result枚举)(Rust Enum、Some(T)、Ok(T)、Err(E))链式操作

文章目录 Rust 枚举之卧龙凤雏枚举的基本概念枚举定义示例 Result 枚举&#xff1a;凤雏Result 枚举的定义Result 的使用场景示例 1&#xff1a;文件读取示例 2&#xff1a;链式操作与错误处理 Option 枚举&#xff1a;卧龙Option 枚举的定义Option 的使用场景示例 1&#xff1…...

TCP/IP协议,TCP和UDP区别

TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff0c;传输控制协议/互联网协议&#xff09;是一组用于计算机网络中的通信协议&#xff0c;它为数据传输提供了标准框架&#xff0c;广泛用于互联网和局域网中。TCP/IP协议包括多个层次&#xff0c;每…...

【go从零单排】Timer、Epoch 时间函数

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 在 Go 语言中&#xff0c;time.Timer 是一个用于在指定时间后执行操作的计时器。…...

壁仞科技上市前最后一波 校招 社招 内推

随着美国大选结束&#xff0c;国内GPU 产业得到空前的的发展空间&#xff0c;国内芯片相关股票一片飘红。 国内大型 GPU厂商壁仞科技&#xff0c;摩尔线程等正紧锣密鼓地加紧上市。 GPGPU 芯片赛道来到了史无前例的红利点&#xff0c;抓住机会&#x1f4aa; 壁仞科技正在火热…...

【微软报告:多模态基础模型】(2)视觉理解

欢迎关注【youcans的AGI学习笔记】原创作品 【微软报告&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软报告&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微软报告&#xff1a;多模态基础模型】&#xff08;3&#xff09;…...

Linux 驱动

四十三、Linux设备树 43.1 DTS、DTB 和 DTC DTS 是设备树源码文件 DTB 是将DTS 编译以后得到的二进制文件。 DTC 工具将.dts 编译为.dtb 43.2 DTS语法 43.2.1 .dtsi 头文件 在.dts 设备树文件中&#xff0c;可以通过“#include”来引用.h、.dtsi 和.dts 文件。 …...

【数学二】线性代数-线性方程组-齐次线性方程组、非齐次线性方程组

考试要求 1、会用克拉默法则. 2、理解齐次线性方程组有非零解的充分必要条件及非齐次线性方程组有解的充分必要条件. 3、理解齐次线性方程组的基础解系及通解的概念,掌握齐次线性方程组基础解系和通解的求法. 4、理解非齐次线性方程组的解的结构及通解的概念. 5、会用初等行变…...

Git别名设置

在 Git 中设置命令别名可以让你更高效地使用常见的 Git 命令。通过为常用命令创建简短的别名&#xff0c;可以减少输入的字符数并加速工作流程。 参考链接 设置 Git 命令别名的方法&#xff1a; 使用 Git 配置命令&#xff1a; Git 允许通过 git config 命令来设置命令别名。这…...

算法基础 -- 红黑树原理与插入伪代码

红黑树原理与插入伪代码 红黑树的原理 红黑树是一种自平衡的二叉搜索树&#xff0c;通过对节点的颜色&#xff08;红色或黑色&#xff09;以及结构的约束条件来保持树的平衡。红黑树的原理可以通过以下五个特性描述&#xff1a; 节点是红色或黑色。根节点必须是黑色。所有叶…...

力扣 LeetCode 27. 移除元素(Day1:数组)

解题思路&#xff1a; 注意&#xff1a;数组只能覆盖&#xff0c;不能删除 erase方法的复杂度为O( n )而不是O( 1 )&#xff0c;因为需要把删除后后面的数组向前移动 方法一&#xff1a;双层for循环暴力 方法二&#xff1a;快慢指针 fast表示新数组的元素 slow表示新数组元…...

微服务链路追踪skywalking安装

‌SkyWalking是一个开源的分布式追踪系统&#xff0c;主要用于监控和分析微服务架构下的应用性能。‌ 它提供了分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案&#xff0c;特别适用于微服务、云原生架构和基于容器的环境&#xff08;如Docker、K8s、Mesos&…...

mqtt学习笔记(一)

以解决问题方式逐步学习探索 mqtt使用场景mqtt可能缺点mqtt学习疑问探索1、mqtt主题发布过的历史消息&#xff0c;全新连接的client能消费到吗&#xff1f;2、mqtt的client掉线如何重连&#xff0c;重连后订阅的topic配置还在不&#xff1f;3、mqtt的client掉线重连后&#xff…...

Kafka Eagle 安装教程

目录 前言 一、安装前的准备 1. 系统要求 2. 安装 JDK 3. 安装 Kafka 和 Zookeeper 4. MySQL 环境准备 二、下载并安装 Kafka Eagle 三、配置 Kafka Eagle 1. 编辑配置文件 2. 配置 Kafka 和 Zookeeper 信息 四、启动 Kafka Eagle 五、访问 Kafka Eagle 六、测试功…...

Ajax 获取进度和中断请求

HTML加入一些内容方便看效果和做交互&#xff1a; <div><p>当前传输进度&#xff1a;<span id"progress">0%</span></p><button id"send">发送</button><button id"btn">中断</button> …...

实验5:网络设备发现、管理和维护

实验5&#xff1a;网络设备发现、管理和维护 实验目的及要求&#xff1a; 通过实验&#xff0c;掌握Cisco 路由器和交换机的IOS配置管理。自动从NTP服务器获取时间信息。能够利用TFTP服务器实现路由器和交换机配置文件的备份和恢复。同时验证CDP协议和LLDP协议的网络参数。完…...

kafka 生产经验——数据积压(消费者如何提高吞吐量)

bit --> byte --> kb -->mb -->gb --> tb --> pb --> eb -> zb -->yb...

对等同步身份认证(Simultaneous Authentication of Equals,简称SAE)介绍

对等同步身份认证&#xff08;Simultaneous Authentication of Equals&#xff0c;简称SAE&#xff09;介绍 对等同步身份认证&#xff08;Simultaneous Authentication of Equals&#xff0c;简称SAE&#xff09;是一种基于密码的身份验证方法&#xff0c;用于安全地交换密钥…...

Ubuntu常用的命令

ls -l # 输出当前文件夹下的所有文件的权限大小信息 ls -l 文件名 # 输出当前文件的权限大小信息 du -sh # 查看文件夹下所有文件的大小总和 df -h # 查看当前文件系统各分区的大小 hdparm -Tt /dev/sda1 # 查看分区磁盘的速度 ls -l | grep "^-" | wc -l # 当前目…...

OpenClaw+GLM-4.7-Flash:24小时运行的智能监控助手

OpenClawGLM-4.7-Flash&#xff1a;24小时运行的智能监控助手 1. 为什么需要智能监控助手&#xff1f; 去年我负责维护一个内部文档站点时&#xff0c;经常遇到半夜服务崩溃却无人知晓的情况。直到第二天同事反馈"页面打不开"&#xff0c;我才手忙脚乱地查日志、重…...

提升效率:用快马一键生成网络应用用户认证api模块

最近在开发一个网络应用时&#xff0c;遇到了用户认证模块的重复开发问题。每次新建项目都要从头写注册登录逻辑&#xff0c;不仅耗时还容易出错。后来发现了InsCode(快马)平台的智能生成功能&#xff0c;帮我快速解决了这个问题。 用户认证模块的核心需求 网络应用中&#xff…...

CSSCI论文写作03:确定论文的选题

什么是选题 选题:选择一个适合的研究指向!!! 选择: 而不是创造,创新是内在要求 你要坚信:所有的选题都有前人关注过研究过,我们不求“栽树”,只求“乘凉”,填补什么空白,只能说明自己的浅薄无知。 适合: 个人经验的学术表达,找到那双穿在自己脚上的鞋子没有不能…...

Html2Pdf高性能转换引擎:PHP 7.2-8.4全版本兼容的企业级HTML转PDF解决方案

Html2Pdf高性能转换引擎&#xff1a;PHP 7.2-8.4全版本兼容的企业级HTML转PDF解决方案 【免费下载链接】html2pdf OFFICIAL PROJECT | HTML to PDF converter written in PHP 项目地址: https://gitcode.com/gh_mirrors/ht/html2pdf 在当今企业数字化转型浪潮中&#xf…...

避坑指南:Python操作Word文档最常见的5个错误(python-docx实战心得)

Python-docx实战避坑指南&#xff1a;5个高频错误与解决方案 在自动化办公场景中&#xff0c;Python操作Word文档的需求日益增长&#xff0c;而python-docx库作为主流工具&#xff0c;其易用性背后隐藏着不少"暗礁"。许多开发者在基础教程阶段一帆风顺&#xff0c;却…...

串口转HID实战:CH9329芯片在无外网环境下的应用指南

CH9329芯片串口转HID实战&#xff1a;隔离环境下的设备控制方案 在工业控制、医疗设备和某些特殊应用场景中&#xff0c;经常需要在物理隔离的网络环境下实现设备控制。CH9329芯片作为一款串口转HID&#xff08;人机接口设备&#xff09;的专业芯片&#xff0c;为解决这类问题提…...

SystemVerilog进阶:深入探索随机化约束的高级应用

1. 从基础到进阶&#xff1a;SystemVerilog随机化约束的核心价值 在芯片验证领域&#xff0c;随机化验证已经成为提高验证效率的黄金标准。SystemVerilog的随机化约束机制&#xff0c;就像给验证工程师配备了一个智能数据生成器&#xff0c;可以自动产生符合设计规范的测试场景…...

Microsoft Agent Framework 构建 SubAgent(Multi-Agent)

本文演示如何用 Microsoft Agent Framework 用 Executor Workflow&#xff08;DAG&#xff09;模式实现 SubAgent&#xff08;子代理&#xff09;架构。通过示例代码&#xff08;来自项目的 txt&#xff09;展示并发 Fan‑Out/Fan‑In 的实现、消息路由与聚合策略&#xff0c;…...

OpenClaw技能扩展实战:基于Qwen3-32B开发自定义文件处理器

OpenClaw技能扩展实战&#xff1a;基于Qwen3-32B开发自定义文件处理器 1. 为什么需要自定义文件处理器 上周处理季度数据时&#xff0c;我又遇到了那个老问题&#xff1a;手头有37个CSV文件需要清洗格式、去重合并&#xff0c;还要按日期归档。这种重复性工作既耗时又容易出错…...