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 正是围绕"绑定 + 分离关注点"设计出来的一种架构模式。
它把应用分成三层,各司其职:
- Model :数据与业务逻辑,不关心界面。比如
Person、TodoItem实体、数据访问层。 - View:界面,只负责展示和接收输入。就是 XAML,code-behind 里尽量少写逻辑。
- 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 的本质。
三、环境准备
- Visual Studio 2019 / 2022(Community 版即可)。
- 目标框架:.NET Framework 4.7.2+ 或 .NET 6/7/8(WPF),本系列以 .NET Framework 4.8 为例,代码两边通用。
- 新建一个 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统一管理,第四篇再讲。
六、小结
这一篇你完成了:
- 理解了 MVVM 的三层职责和"绑定 + 通知 + 命令"三大解耦手段。
- 装好了
MvvmLightLibs。 - 用
ViewModelBase+{Binding}跑通了第一个 Hello World。
下一篇我们深入 ViewModelBase,讲清楚 INotifyPropertyChanged 到底是怎么工作的,以及 Set、RaisePropertyChanged、ObservableCollection 的正确用法。
系列导航:第一篇·入门 / 第二篇·ViewModelBase 与属性通知 / 第三篇·RelayCommand 与 Messenger / 第四篇·SimpleIoc 与 ViewModelLocator 及完整实例