MVVM是wpf中分离ui与业务逻辑的架构模式,由View(XAML界面)、ViewModel(封装逻辑并实现INotifyPropertyChanged和ICommand)和Model(数据与业务)组成,依托数据绑定和命令机制实现解耦。

MVVM(Model-View-ViewModel)是WPF中一种广泛应用的架构模式,旨在分离用户界面逻辑与业务逻辑,提升代码的可维护性、可测试性和可重用性。它的核心在于通过数据绑定和命令机制,让View(视图)与ViewModel(视图模型)解耦。
1. MVVM 的基本结构
View(视图):即XAML页面,负责UI展示和用户交互。它不直接操作数据或逻辑,而是通过绑定依赖属性来显示数据,并通过命令响应用户操作。
ViewModel(视图模型):位于View和Model之间,暴露公共属性和命令供View绑定,封装界面逻辑,比如数据验证、状态管理等。它通常实现 INotifyPropertyChanged 接口以支持数据绑定更新。
Model(模型):代表应用程序的数据和业务逻辑,如实体类、数据访问层等,不关心UI细节。
2. 数据绑定的实现
WPF的数据绑定是MVVM的核心。当ViewModel中的数据发生变化时,View能自动更新,前提是属性触发了通知事件。
实现方式如下:
- ViewModel类实现 INotifyPropertyChanged 接口。
- 在属性的setter中调用 PropertyChanged 事件,通知WPF属性已更改。
示例代码:
public class PersonViewModel : INotifyPropertyChanged { private string _name; public string Name { get => _name; set { _name = value; OnPropertyChanged(nameof(Name)); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
在XAML中绑定:
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
这样,当文本框输入变化时,Name属性会自动更新;反之,代码中修改Name,界面也会刷新。
3. 命令(ICommand)的实现
在MVVM中,按钮点击等操作不能使用传统事件处理(如Click事件),而应通过命令绑定,保持View不包含逻辑代码。
使用 ICommand 接口将动作封装为属性,推荐使用 RelayCommand 或 DelegateCommand 简化实现。
自定义 RelayCommand 示例:
public class RelayCommand : ICommand { private readonly Action _execute; private readonly Func<bool> _canExecute; 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; } } }
在ViewModel中定义命令:
public ICommand SaveCommand { get; private set; } public PersonViewModel() { SaveCommand = new RelayCommand(Save, CanSave); } private void Save() { // 执行保存逻辑 } private bool CanSave() => !string.IsNullOrWhiteSpace(Name);
XAML中绑定命令:
<Button Content="保存" Command="{Binding SaveCommand}" />
此时按钮是否可用会根据 CanSave() 返回值动态更新。
4. 实际应用建议
- 使用NuGet包如 CommunityToolkit.Mvvm(原MvvmHelpers)可简化 ViewModel 基类和命令的编写。
- 避免在View中写后台代码(code-behind),除非必须操作UI元素。
- 合理使用 ObservableCollection
绑定列表数据,确保集合变更也能反映到界面。
基本上就这些。掌握数据绑定和命令机制,就能在WPF中高效使用MVVM模式,写出清晰、易测的界面代码。