.NET Community Toolkit

Posted by Andy Feng on June 27, 2025

Introduction

.NET Community Toolkit(简称 Community ToolkitToolkit)是微软和社区联合开发的一个开源库集合,2021年左右基于以前各类微软辅助库的基础上推出。旨在为 .NET 应用开发者提供一组高效、易用且现代化的工具和辅助库,提升开发效率和代码质量。

它主要聚焦于:

  • MVVM 模式支持(主要针对 WPF、WinUI、UWP 等桌面与现代应用)
  • 性能优化(如高性能集合和辅助类)
  • 简化常见任务(如事件处理、消息传递、数据绑定等)

    发展历程:

| 时间 | 事件/版本 | 说明 | | ——— | ———————————- | —————————————– | | 2016-2018 | Windows Community Toolkit | 针对 UWP 的社区工具库,微软主导,包含控件、MVVM、辅助方法等。 | | 2019-2020 | 工具包逐渐成熟,支持多种UWP特性 | 增加更多控件和扩展,社区贡献活跃。 | | 2021年 | 重构成 .NET Community Toolkit | 重命名并开始支持 WinUI 3 和更广泛的 .NET 平台(包括 WPF)。 | | 2021-2023 | 模块化拆分,MVVM Toolkit 独立 | MVVM Toolkit 模块脱离主工具包,成为独立的 NuGet 包,简洁轻量。 | | 2023-2024 | 支持 .NET 6 / 7 / MAUI,加入更多性能优化和扩展集合 | 持续更新,增强性能,支持跨平台(WinUI、WPF、MAUI)。 | | 2025年+ | 持续迭代,聚焦开发者体验和跨平台支持 | 预计将增强与 Blazor 等新兴框架集成,强化开发者工具链。 |

为什么使用MVVC Toolkit?

|问题(过去的 MVVM)|MVVM Toolkit 的解决方案| |—|—| |要手写 INotifyPropertyChanged|✅ 用 [ObservableProperty] 自动生成| |要写一堆 RelayCommand|✅ 用 [RelayCommand] 自动生成命令| |属性变更还要手动 OnPropertyChanged()|✅ 自动生成通知逻辑| |手写命令类重复代码多|✅ 一个属性 + 属性名 = 自动生成命令| |没有统一风格|✅ 微软官方风格,轻量、现代、跨平台|

Install

NuGet 安装 CommunityToolkit.Mvvm or dotnet add package CommunityToolkit.Mvvm 这是最常用、最核心的 MVVM 模块。其他模块(如 Collections、Diagnostics)可以根据需要添加。

| 模块名称 | 功能简介 | | ———————————- | ———————————————– | | CommunityToolkit.Mvvm | MVVM 支持:ObservableObject, RelayCommand, 消息等 | | CommunityToolkit.Collections | 高性能集合,支持异步分页、线程安全集合等 | | CommunityToolkit.Diagnostics | 更智能的调试辅助,如 Guard | | CommunityToolkit.HighPerformance | 针对 Span/Memory 的性能优化方法 | | CommunityToolkit.WinUI | 针对 WinUI 的 UI 扩展和控件(适用于 WinUI 项目) | MVVM Toolkit 核心功能

|功能|用法例子| |—|—| |自动实现属性通知|[ObservableProperty] string name; → 自动生成属性和通知| |自动生成命令|[RelayCommand] void Save() → 自动生成 SaveCommand| |异步命令支持|[RelayCommand] async Task LoadAsync()| |属性变化通知关系|[NotifyPropertyChangedFor(nameof(IsValid))]| |ViewModel 基类|ObservableObject, ObservableRecipient, ObservableValidator| |消息通信(解耦)|IMessenger, WeakReferenceMessenger|

How to use

一个简单的 WPF MVVM 例子,功能是一个文本输入框和一个按钮,点击按钮后弹出输入内容的消息框。

  • 一个 TextBox 双向绑定 UserInput 属性
  • 一个按钮绑定 ShowMessageCommand
  • 点击按钮,弹出消息框显示当前 UserInput 内容

    传统写法:没有用 .NET Community Toolkit,自己实现 INotifyPropertyChangedICommand

    ViewModel.cs

using System;
using System.ComponentModel;
using System.Windows.Input;

public class MainViewModel : INotifyPropertyChanged
{
    private string _userInput;

    public string UserInput
    {
        get => _userInput;
        set
        {
            if (_userInput != value)
            {
                _userInput = value;
                OnPropertyChanged(nameof(UserInput));
            }
        }
    }

    public ICommand ShowMessageCommand { get; }

    public MainViewModel()
    {
        ShowMessageCommand = new RelayCommand(ShowMessage);
    }

    private void ShowMessage()
    {
        System.Windows.MessageBox.Show($"你输入了: {UserInput}");
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    protected void OnPropertyChanged(string propertyName) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

// ICommand 实现
public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool>? _canExecute;

    public RelayCommand(Action execute, Func<bool>? canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }

    public bool CanExecute(object? parameter) => _canExecute?.Invoke() ?? true;

    public void Execute(object? parameter) => _execute();

    public event EventHandler? CanExecuteChanged;

    public void RaiseCanExecuteChanged() =>
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}

MainWindow.xaml (View)

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="传统写法" Height="150" Width="300">
    <StackPanel Margin="20">
        <TextBox Text="{Binding UserInput, UpdateSourceTrigger=PropertyChanged}" />
        <Button Content="显示消息" Command="{Binding ShowMessageCommand}" Margin="0,10,0,0"/>
    </StackPanel>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}

使用 Community Toolkit:用它自带的 ObservableObjectRelayCommand,代码简洁很多。

ViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Windows;

public partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    private string userInput;

    public MainViewModel()
    {
        ShowMessageCommand = new RelayCommand(() =>
        {
            MessageBox.Show($"你输入了: {UserInput}");
        });
    }

    public RelayCommand ShowMessageCommand { get; }
}

注意:

  • [ObservableProperty] 特性自动生成 UserInput 属性和通知代码
  • 直接用 RelayCommand,不用自己写 ICommand 实现

MainWindow.xaml (View) 不变

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="传统写法" Height="150" Width="300">
    <StackPanel Margin="20">
        <TextBox Text="{Binding UserInput, UpdateSourceTrigger=PropertyChanged}" />
        <Button Content="显示消息" Command="{Binding ShowMessageCommand}" Margin="0,10,0,0"/>
    </StackPanel>
</Window>

MainWindow.xaml.cs 不变

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}

对比

|点|传统写法|使用 Toolkit| |—|—|—| |代码量|较多,需要手动写 INotifyPropertyChangedICommand 实现|非常简洁,属性和命令通过特性和基类自动生成| |可维护性|代码重复、易错,特别是属性通知|结构清晰,减少样板代码| |学习曲线|理解接口细节较多|更易上手,专注业务逻辑| |性能|好,但写法繁琐|利用 source generators 优化性能| |社区和微软支持|需要自己维护和测试|官方支持,持续更新,社区活跃|

FAQ

References

.NET Community Toolkit source code github # Windows Community Toolkit Documentation