新闻中心

C# 如何在 WPF 中使用 MVVM 模式_C# WPF MVVM 模式应用教程

2025-11-06
浏览次数:
返回列表
答案:本文介绍了在WPF中通过MVVM模式实现界面与业务逻辑分离的方法,包括创建Models、ViewModels和Views三层结构,使用INotifyPropertyChanged接口实现数据绑定,通过RelayCommand处理用户命令,并在XAML中绑定DataContext与ICommand,从而实现解耦和可维护的代码架构。

c# 如何在 wpf 中使用 mvvm 模式_c# wpf mvvm 模式应用教程

在 WPF 中使用 MVVM(Model-View-ViewModel)模式,可以让界面与业务逻辑清晰分离,提升代码的可维护性和可测试性。下面介绍如何在 C# WPF 项目中实现 MVVM 模式,从结构搭建到数据绑定和命令处理。

创建基本项目结构

新建一个 WPF 应用程序后,建议按功能划分文件夹,使结构更清晰:

  • Views:存放 XAML 界面文件(如 MainWindow.xaml、UserControl 等)
  • ViewModels:存放 ViewModel 类,负责提供 View 所需的数据和命令
  • Models:存放数据模型,表示业务实体

例如,创建一个简单的用户信息展示功能:

Models/User.cs
public 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.cs
public 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.cs
using 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调用】 

搜索