WPF MVVM Light 入门:从零到Hello World

WPF MVVM Light 入门(一):认识 MVVM、搭建环境、跑通 Hello World

系列导航:第一篇·入门 / 第二篇·ViewModelBase 与属性通知 / 第三篇·RelayCommand 与 Messenger / 第四篇·SimpleIoc 与 ViewModelLocator 及完整实例

写在前面

本系列带你从零掌握 WPF 中经典的轻量级 MVVM 框架 ------ MVVM Light(GalaSoft.MvvmLight)。

先说一个重要前提,避免你踩坑:MVVM Light 已由作者 Laurent Bugnion 于 2018 年停止维护并归档,官方推荐新项目迁移到 CommunityToolkit.Mvvm(微软 MVVM Toolkit)。但这不影响它的学习价值------大量老项目、教学案例和面试题依然基于 MVVM Light,吃透它也能让你更快上手任何 MVVM 框架。本系列用它入门,核心思路是通用的。

一、什么是 MVVM

WPF 最大的优势之一是数据绑定(Data Binding),而 MVVM 正是围绕"绑定 + 分离关注点"设计出来的一种架构模式。

它把应用分成三层,各司其职:

  1. Model :数据与业务逻辑,不关心界面。比如 PersonTodoItem 实体、数据访问层。
  2. View:界面,只负责展示和接收输入。就是 XAML,code-behind 里尽量少写逻辑。
  3. ViewModel :视图的"抽象",暴露 View 要绑定的属性命令,承载交互逻辑。

三者通过三件事解耦:

  • 绑定 :View 的 DataContext 指向 ViewModel,XAML 用 {Binding} 关联属性。
  • 通知 :ViewModel 实现 INotifyPropertyChanged,属性变化时通知 View 刷新。
  • 命令 :View 通过 ICommand(而非 Click 事件)触发 ViewModel 的操作。

对比传统写法------在按钮的 Click 事件里直接操作控件:

csharp 复制代码
// 传统 code-behind 写法(不推荐)
private void Button_Click(object sender, RoutedEventArgs e)
{
    myTextBlock.Text = myTextBox.Text;
}

MVVM 的写法把这段逻辑搬进 ViewModel,界面只负责绑定:

xml 复制代码
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="{Binding Name}" />

好处很明显:逻辑可脱离界面单独测试、界面和业务解耦、维护成本低。这也正是 MVVM 在 WPF 社区长盛不衰的原因。

二、为什么选 MVVM Light

市面上主流 MVVM 框架有 Prism、Caliburn.Micro、CommunityToolkit.Mvvm 等,MVVM Light 的特点是:

  • 轻量:只提供最核心的能力,没有学习负担。
  • 曲线平缓:四个组件就能覆盖 90% 场景,非常适合入门。
  • 四大件ViewModelBase(属性通知)、RelayCommand(命令)、Messenger(消息)、SimpleIoc(依赖注入)。

一句话:Prism 适合大型复杂项目,MVVM Toolkit 更现代,而 MVVM Light 最适合用来理解 MVVM 的本质

三、环境准备

  1. Visual Studio 2019 / 2022(Community 版即可)。
  2. 目标框架:.NET Framework 4.7.2+ 或 .NET 6/7/8(WPF),本系列以 .NET Framework 4.8 为例,代码两边通用。
  3. 新建一个 WPF 项目:文件 → 新建 → 项目 → WPF 应用,命名为 TodoApp

四、安装 MVVM Light

通过 NuGet 安装库包 MvvmLightLibs(只含核心库,推荐)。

Package Manager Console:

复制代码
Install-Package MvvmLightLibs

或者图形界面:右键项目 → 管理 NuGet 程序包 → 搜索 MvvmLightLibs → 安装。

注意 :还有一个 MvvmLight 包(含项目模板和更多依赖),老项目常用,但依赖较重。新版建议直接用 MvvmLightLibs,它只引入核心库,并会自动带上 CommonServiceLocator 依赖。

安装完成后,就可以使用命名空间 GalaSoft.MvvmLight 了。

五、Hello World:跑通第一个绑定

目标:一个 TextBox 输入,下方 TextBlock 实时显示同样的内容(双向绑定 + 属性通知)。

5.1 创建 ViewModel

新建 ViewModels 文件夹,创建 MainViewModel.cs

csharp 复制代码
using GalaSoft.MvvmLight;

namespace TodoApp.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        private string _name;

        public string Name
        {
            get => _name;
            set => Set(ref _name, value);
        }
    }
}

这里的关键点:

  • 类继承自 ViewModelBase
  • 属性用 Set(ref _name, value) 赋值,它会自动判断值是否真的变了,变了才触发属性通知。这一篇先记住用法,原理在第二篇详细展开。

5.2 编写界面

打开 MainWindow.xaml,替换为:

xml 复制代码
<Window x:Class="TodoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:TodoApp.ViewModels"
        Title="MVVM Light Hello World" Height="200" Width="360">
    <Window.DataContext>
        <vm:MainViewModel />
    </Window.DataContext>
    <StackPanel Margin="16">
        <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"
                 Height="30" VerticalContentAlignment="Center" />
        <TextBlock Text="{Binding Name}" Margin="0,12,0,0" FontSize="18" />
    </StackPanel>
</Window>

两个绑定要点:

  • UpdateSourceTrigger=PropertyChanged:让 TextBox 每次输入都立刻把值写回 ViewModel,而不是等失去焦点。这是"实时显示"的关键。
  • Text="{Binding Name}":TextBlock 只读,绑定同一个属性即可。

5.3 运行

直接 F5 运行。在输入框打字,下面文字会同步变化------你已经跑通了 MVVM 最核心的"属性 + 通知 + 绑定"闭环。

这里为了让第一篇最小化,我在 XAML 里手动 new 了 MainViewModel。实际项目会用 ViewModelLocator 统一管理,第四篇再讲。

六、小结

这一篇你完成了:

  1. 理解了 MVVM 的三层职责和"绑定 + 通知 + 命令"三大解耦手段。
  2. 装好了 MvvmLightLibs
  3. ViewModelBase + {Binding} 跑通了第一个 Hello World。

下一篇我们深入 ViewModelBase,讲清楚 INotifyPropertyChanged 到底是怎么工作的,以及 SetRaisePropertyChangedObservableCollection 的正确用法。


系列导航第一篇·入门 / 第二篇·ViewModelBase 与属性通知 / 第三篇·RelayCommand 与 Messenger / 第四篇·SimpleIoc 与 ViewModelLocator 及完整实例

相关推荐
曹牧2 小时前
C#:函数参数指定默认值
开发语言·c#
李高钢3 小时前
WPF MVVM Light(三):RelayCommand 命令与 Messenger 消息
前端·c#·wpf
曹牧8 小时前
C#:字符串做20位截断
开发语言·c#
离陌在学C#18 小时前
C# 事件(Event)详解:从概念到实战
开发语言·c#
rockey62720 小时前
C#脚本引擎之AScript与Flee对比
c#·.net·script·eval·动态脚本
zjnlswd1 天前
C#学习笔记4
笔记·学习·c#
曹牧1 天前
C#:List<string>特定格式输出
windows·c#
Z5998178411 天前
c#软件开发学习笔记--Modbus-TCP/UDP网口通讯
笔记·学习·c#
曹牧1 天前
C#:取的多个药品批准文号中的一个
c#