本文将详细介绍如何在 WinForm 应用程序中使用 CommunityToolkit.Mvvm 结合依赖注入实现 MVVM 模式。我们将通过一个具体的示例来展示整个实现过程。
首先需要安装以下 NuGet 包:
XML<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />

C#├── Models │ └── UserModel.cs ├── ViewModels │ └── MainViewModel.cs ├── Views │ └── MainForm.cs ├── Services │ └── IUserService.cs │ └── UserService.cs └── Program.cs
C#// Models/UserModel.cs
public class UserModel
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
C#// Services/IUserService.cs
public interface IUserService
{
Task<List<UserModel>> GetUsersAsync();
Task<bool> AddUserAsync(UserModel user);
}
// Services/UserService.cs
public class UserService : IUserService
{
// 模拟数据库
private readonly List<UserModel> _users = new();
public async Task<List<UserModel>> GetUsersAsync()
{
// 模拟异步操作
await Task.Delay(100);
return _users;
}
public async Task<bool> AddUserAsync(UserModel user)
{
await Task.Delay(100);
_users.Add(user);
return true;
}
}
C#// ViewModels/MainViewModel.cs
public partial class MainViewModel : ObservableObject
{
private readonly IUserService _userService;
[ObservableProperty]
private ObservableCollection<UserModel> users = new();
[ObservableProperty]
private string userName;
[ObservableProperty]
private int userAge;
public MainViewModel(IUserService userService)
{
_userService = userService;
// 构造函数中加载数据
LoadUsersAsync().ConfigureAwait(false);
}
// 加载用户列表
private async Task LoadUsersAsync()
{
var userList = await _userService.GetUsersAsync();
Users = new ObservableCollection<UserModel>(userList);
}
// 添加用户命令
[RelayCommand]
private async Task AddUserAsync()
{
if (string.IsNullOrEmpty(UserName))
return;
var user = new UserModel
{
Name = UserName,
Age = UserAge
};
var result = await _userService.AddUserAsync(user);
if (result)
{
Users.Add(user);
// 清空输入
UserName = string.Empty;
UserAge = 0;
}
}
}
C#using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using App12.ViewModels;
using static System.Net.Mime.MediaTypeNames;
namespace App12.Views
{
public partial class MainForm : Form
{
private readonly MainViewModel _viewModel;
private BindingSource bindingSource; // 声明为类成员
public MainForm(MainViewModel viewModel)
{
InitializeComponent();
_viewModel = viewModel;
// 设置数据绑定
SetupDataBindings();
// 设置命令绑定
SetupCommandBindings();
}
private void SetupDataBindings()
{
// 用户列表绑定
bindingSource = new BindingSource();
bindingSource.DataSource = _viewModel.Users;
dataGridView1.DataSource = bindingSource;
// 文本框绑定
txtName.DataBindings.Add(new Binding("Text", _viewModel,
nameof(_viewModel.UserName), true, DataSourceUpdateMode.OnPropertyChanged));
numAge.DataBindings.Add(new Binding("Value", _viewModel,
nameof(_viewModel.UserAge), true, DataSourceUpdateMode.OnPropertyChanged));
}
private void SetupCommandBindings()
{
// 添加用户按钮点击事件
btnAdd.Click += async (s, e) =>
{
await _viewModel.AddUserCommand.ExecuteAsync(null);
var result = _viewModel.Users;
bindingSource.ResetBindings(false);
};
}
}
}
这里没找到好的方法像WPF一样ObservableCollection 通知datagrid 。
C#using App12.Services;
using App12.ViewModels;
using App12.Views;
using Microsoft.Extensions.DependencyInjection;
namespace App12
{
internal static class Program
{
public static IServiceProvider ServiceProvider { get; private set; }
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
// 配置依赖注入
var services = new ServiceCollection();
ConfigureServices(services);
ServiceProvider = services.BuildServiceProvider();
// 从服务容器中获取主窗体并运行
var mainForm = ServiceProvider.GetRequiredService<MainForm>();
Application.Run(mainForm);
}
private static void ConfigureServices(IServiceCollection services)
{
// 注册服务
services.AddSingleton<IUserService, UserService>();
// 注册 ViewModel
services.AddTransient<MainViewModel>();
// 注册主窗体
services.AddTransient<MainForm>();
}
}
}

这个示例展示了如何在 WinForm 应用程序中使用 CommunityToolkit.Mvvm 和依赖注入。通过遵循 MVVM 模式,可以使代码更加清晰、可维护,同时也便于进行单元测试。虽然 WinForm 不像 WPF 那样天生支持 MVVM 模式,但通过适当的设计和工具的使用,同样可以实现清晰的分层架构。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!