新闻中心
C# 如何在 WPF 中使用 MVVM 模式_C# WPF MVVM 模式应用教程
答案:本文介绍了在WPF中通过MVVM模式实现界面与业务逻辑分离的方法,包括创建Models、ViewModels和Views三层结构,使用INotifyPropertyChanged接口实现数据绑定,通过RelayCommand处理用户命令,并在XAML中绑定DataContext与ICommand,从而实现解耦和可维护的代码架构。

在 WPF 中使用 MVVM(Model-View-ViewModel)模式,可以让界面与业务逻辑清晰分离,提升代码的可维护性和可测试性。下面介绍如何在 C# WPF 项目中实现 MVVM 模式,从结构搭建到数据绑定和命令处理。
创建基本项目结构
新建一个 WPF 应用程序后,建议按功能划分文件夹,使结构更清晰:
- Views:存放 XAML 界面文件(如 MainWindow.xaml、UserControl 等)
- ViewModels:存放 ViewModel 类,负责提供 View 所需的数据和命令
- Models:存放数据模型,表示业务实体
例如,创建一个简单的用户信息展示功能:
Models/User.cspublic class User
{
public string Name { get; set; }
public int Age { get; set; }
}ViewModels/MainViewModel.cs
using System.ComponentModel;
<p>public class MainViewModel : INotifyPropertyChanged
{
private string _name;
private int _age;</p><pre class="brush:php;toolbar:false;">public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
public int Age
{
get => _age;
set
{
_age = value;
OnPropertyChanged(nameof(Age));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}}
设置数据绑定
在 View 中绑定 ViewModel 的属性,让界面自动响应数据变化。
Views/MainWindow.xaml<Window x:Class="MvvmApp.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MVVM 示例" Height="200" Width="300">
<StackPanel Margin="20">
<TextBlock Text="姓名:" />
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="年龄:" Margin="0,10,0,0" />
<TextBox Text="{Binding Age, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Window>在窗口加载时设置 DataContext:
MainWindow.xaml.cspublic partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}这样,文本框会自动显示 ViewModel 中的值,并在用户输入时更新属性。
使用 ICommand 处理用户操作
ViewModel 不应直接引用 UI 元素,通过 ICommand 实现按钮点击等交互。
添加一个“保存”命令到 ViewModel:
刺鸟创客
一款专业高效稳定的AI内容创作平台
110
查看详情
using System.Windows.Input;
<p>public class MainViewModel : INotifyPropertyChanged
{
// ... 其他属性</p><pre class="brush:php;toolbar:false;">public ICommand S*eCommand => new RelayCommand(S*e);
private void S*e()
{
MessageBox.Show($"保存用户:{Name}, 年龄:{Age}");
}
// 实现 INotifyPropertyChanged ...}
需要定义一个简单的 RelayCommand:
Commands/RelayCommand.csusing System;
using System.Windows.Input;
<p>public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;</p><pre class="brush:php;toolbar:false;">public RelayCommand(Action execute, Func<bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute();
public void Execute(object parameter) => _execute();
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}}
在 XAML 中绑定命令:
<Button Content="保存" Command="{Binding S*eCommand}" Margin="0,10" />点击按钮时会调用 ViewModel 中的 S*e 方法,完全解耦 UI 和逻辑。
整合资源与导航(可选进阶)
大型应用中,可以使用 ViewModelLocator 或依赖注入容器(如 Microsoft.Extensions.DependencyInjection)统一管理 ViewModel 创建。
也可以通过 Messenger 或事件聚合器实现跨 ViewModel 通信,避免紧耦合。
基本上就这些。掌握属性通知、数据绑定和命令机制,就能在 WPF 中有效使用 MVVM 模式。不复杂但容易忽略细节,比如忘记设置 DataContext 或未正确触发 PropertyChanged。多练习几个小功能,很快就能上手。
以上就是C# 如何在 WPF 中使用 MVVM 模式_C# WPF MVVM 模式应用教程的详细内容,更多请关注其它相关文章!
# 如何选择
# 营口排名优化seo
# 宜春如何seo搜索优化
# 济宁专业seo引擎优化
# seo tfid
# 宁夏短视频seo公司排行
# 韶关个人网站建设
# 汉阳网站建设哪家便宜
# 智慧网站建设要点
# 卫浴网站推广单价
# seo公司招商加盟
# 进阶
# 意味着什么
# windows
# 开源
# 有什么区别
# 这对
# 微软
# 并在
# 如何在
# 绑定
# c#
# microsoft
# win
# ai
# app
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
MinIO大规模对象列表性能瓶颈深度解析与外部元数据管理策略
WordPress插件开发:正确注册卸载钩子与避免常见陷阱
Typer应用中灵活处理命令行参数的令牌化与解析
抓大鹅无需下载版 抓大鹅秒玩版入口
XML中包含HTML标签导致解析错误? 正确嵌入非XML数据的两种方法
word中如何让数字纵向排列_Word数字纵向排列方法
Django AJAX 文件上传教程:解决图片无法保存到模型的常见问题
黑猫投诉统一入口官网 消费者权益保护投诉平台
Win11怎么用U盘重装系统 Win11制作启动盘并重装系统完整教程【详解】
TikTok网页版直接登录 TikTok网页端官方平台入口
如何将HTML表格多行数据保存到Google Sheet
PySpark中从现有列右侧提取可变长度字符创建新列的教程
J*a实现学校排课程序_面向对象结构化项目示例
Bilibili动漫最新防封地址发布-Bilibili动漫2025年最稳正版入口推荐
J*aScript实现动态背景色下的文本与按钮颜色自适应调整
支付宝解绑银行卡步骤_支付宝如何解除绑定银行卡
微信网页版官方入口教程 微信网页版网页版快速登录步骤
怎样使用“本地安全策略”提升Windows安全性_Secpol.msc配置指南【高手】
J*aScript map 迭代中检测空数组元素的有效方法
漫蛙漫画登录站点 漫蛙2正版漫画快速访问
京东单号查询入口_京东快递订单追踪入口
c++中的std::forward_list和std::list有什么不同_c++ forward_list与list区别分析
J*aScript类型检查_j*ascript代码规范
J*aScript动态修改指定div内所有a标签样式指南
sublime侧边栏怎么增强功能_SideBarEnhancements for sublime安装与配置
2026年发布! 美少女养成动作RPG《神剑少女战记》发布实机演示
移动端XML文件怎么转换成Excel 手机和平板上的解决方案
C++指针和引用有什么区别_C++内存管理核心概念深度解析
J*aScript数组对象转换:按指定键分组与值收集
C++如何进行游戏物理模拟_使用Box2D库为C++游戏添加2D物理效果
PDF怎么合并PDF并保持格式_PDF合并文件保持排版教程
AI抖音网页版免费视频入口 AI抖音网页端最新视频实时观看
Win11怎么查看显卡显存 Win11显示适配器属性及专用视频内存查询
抖音网页版企业服务中心登录入口_抖音网页版企业登录平台
KFC套餐升级怎么获取优惠代码_KFC套餐升级活动与优惠代码获取方法
Selenium Python中处理点击后新窗口加载冻结问题的策略与实践
抖音隐秘迷城小游戏入口_ 抖音冒险解谜小游戏秒玩
解决Django多数据库/多Schema环境下外键迁移问题
使用Python高效删除Word宏并转换DOCM为DOCX格式
铁路12306改签能改到更早的车次吗_铁路12306改签提前车次规则
Composer中的^和~符号代表什么_精通Composer版本号语义化约束
Mac怎么锁定备忘录_Mac备忘录加密设置教程
必由学官网快捷入口 必由学网页版在线学习平台
Pandas DataFrame 高效批量赋值:告别循环与笛卡尔积误区
痛风发作了怎么办? 快速止痛和后期饮食调理
Golang如何实现状态模式管理对象状态_Golang State模式实现技巧
Composer的 archive 命令怎么用_快速打包你的PHP项目及其Composer依赖
Golang如何通过reflect获取匿名字段方法_Golang reflect匿名字段方法访问技巧
必由学网页版入口 必由学官方平台直接访问
文心一言怎样用插件调度API数据_文心一言用插件调度API数据【API调用】


2025-11-06
浏览次数:次
返回列表