WPF MVVM框架 - CommunityToolkit.Mvvm 使用简介
WPF 的 CommunityToolkit.Mvvm(简称 MVVM Toolkit)是微软官方推出的轻量级 MVVM 框架,旨在简化 MVVM 模式在 WPF、UWP、WinUI 等应用中的实现。它通过 源代码生成器 和简洁的 API 减少样板代码,提高开发效率。
主要特性
轻量且高效
基于现代 C# 特性(如 partial class 和 Source Generators),减少手动编写的代码量。
强类型通知
自动生成属性通知逻辑,避免手写 INotifyPropertyChanged 实现。
命令简化
提供 RelayCommand 和 AsyncRelayCommand,简化命令绑定。
依赖注入支持
支持通过 Ioc 类实现简单的依赖注入。
消息机制
提供 Messenger 实现组件间松耦合通信。
安装使用
通过 NuGet 安装包:
Install-Package CommunityToolkit.Mvvm核心组件
1. ObservableObject
ViewModel 的基类,自动实现 INotifyPropertyChanged 接口。
using CommunityToolkit.Mvvm.ComponentModel;
public partial class MyViewModel : ObservableObject
{
[ObservableProperty]
private string _name; // 自动生成 public 属性 Name,并在赋值时触发 PropertyChanged 事件
} // OnPropertyChanged() 通知UI属性值更改
public class MainWindowViewModel : ObservableObject
{
public string? userName;
public string? UserName { get { return userName; } set { userName = value; OnPropertyChanged(); } }
public string? password;
public string? Password { get { return password; } set { password = value; OnPropertyChanged(); } }
private string? message;
public string? Message { get { return message; } set { message = value; OnPropertyChanged(); } }
}2. RelayCommand
简化命令绑定,支持同步和异步操作。
using CommunityToolkit.Mvvm.Input;
public partial class MyViewModel : ObservableObject
{
[RelayCommand]
private void Submit()
{
// 执行提交逻辑
}
[RelayCommand(CanExecute = nameof(CanLoadData))]
private async Task LoadDataAsync()
{
// 异步加载数据
}
private bool CanLoadData() => !IsBusy;
} public class MainWindowViewModel : ObservableObject
{
// 在ViewModel中定义命令
public RelayCommand LoginCommand { get; set; }
public MainWindowViewModel()
{
LoginCommand = new RelayCommand(Login);
}
public void Login()
{
MessageBox.Show("点击了登录");
// TO DO: 登录逻辑
// ...
Message = "登录成功";
UserName = "";
Password = "";
// 发送消息
WeakReferenceMessenger.Default.Send("123", "login-cussess");
}
}3. Messenger
跨组件消息传递(发布-订阅模式)。
// 定义消息
public class LoginSuccessMessage { }
// 发送消息
Messenger.Send(new LoginSuccessMessage());
// 接收消息
Messenger.Register<LoginSuccessMessage>(this, (recipient, message) =>
{
// 处理消息
}); public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
// 接收消息
WeakReferenceMessenger.Default.Register<string, string>(this, "login-cussess", (s, e) =>
{
MessageBox.Show("登录成功");
});
}
public class MainWindowViewModel : ObservableObject
{
public string? userName;
public string? UserName { get { return userName; } set { userName = value; OnPropertyChanged(); } }
public string? password;
public string? Password { get { return password; } set { password = value; OnPropertyChanged(); } }
private string? message;
public string? Message { get { return message; } set { message = value; OnPropertyChanged(); } }
// 在ViewModel中定义命令
public RelayCommand LoginCommand { get; set; }
public MainWindowViewModel()
{
LoginCommand = new RelayCommand(Login);
}
public void Login()
{
MessageBox.Show("点击了登录");
// TO DO: 登录逻辑
// ...
Message = "登录成功";
UserName = "";
Password = "";
// 发送消息
WeakReferenceMessenger.Default.Send("123", "login-cussess");
}
}4. Ioc 依赖注入
简易的依赖注入容器。
// 注册服务
Ioc.Default.ConfigureServices(services =>
{
services.AddSingleton<ILogger, FileLogger>();
});
// 获取服务
var logger = Ioc.Default.GetService<ILogger>();基础使用示例
ViewModel 实现
public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
private string _userName;
[ObservableProperty]
private int _count;
[RelayCommand]
private void IncrementCount()
{
Count++;
}
[RelayCommand(CanExecute = nameof(CanResetCount))]
private void ResetCount()
{
Count = 0;
}
private bool CanResetCount => Count > 0;
}<Window DataContext="{Binding MainViewModel}">
<StackPanel>
<TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding Count}"/>
<Button Content="Increment" Command="{Binding IncrementCountCommand}"/>
<Button Content="Reset" Command="{Binding ResetCountCommand}"/>
</StackPanel>
</Window>高级功能
嵌套属性通知
使用 NotifyPropertyChangedFor 特性通知关联属性:
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FullName))]
private string _firstName;
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FullName))]
private string _lastName;
public string FullName => $"{FirstName} {LastName}";异步命令
使用 AsyncRelayCommand 处理异步操作
[RelayCommand]
private async Task LoadDataAsync()
{
await Task.Delay(1000);
// 加载数据
}验证支持
结合 DataAnnotation 或自定义逻辑实现输入验证
最佳实践
代码结构:将 ViewModel 放在独立项目或文件夹(如 ViewModels)中。
命名规范:私有字段使用下划线前缀(如 _userName),生成的公共属性名自动转为 UserName。
解耦:通过 Messenger 实现组件间通信,避免直接引用。
其他MVVM框架
比如Prism或MVVM Light