编辑
2025-11-25
C#
00

目录

概述
环境准备
项目结构
详细代码实现
Model 层
Service 层
ViewModel 层
View 层
程序入口配置依赖注入
注意事项
优势
总结

概述

本文将详细介绍如何在 WinForm 应用程序中使用 CommunityToolkit.Mvvm 结合依赖注入实现 MVVM 模式。我们将通过一个具体的示例来展示整个实现过程。

环境准备

首先需要安装以下 NuGet 包:

XML
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />

image.png

项目结构

C#
├── Models │ └── UserModel.cs ├── ViewModels │ └── MainViewModel.cs ├── Views │ └── MainForm.cs ├── Services │ └── IUserService.cs │ └── UserService.cs └── Program.cs

详细代码实现

Model 层

C#
// Models/UserModel.cs public class UserModel { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }

Service 层

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; } }

ViewModel 层

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; } } }

View 层

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>(); } } }

image.png

注意事项

  1. WinForms 的数据绑定相对 WPF 较为简单,需要手动设置
  2. 确保在 UI 线程上更新界面元素
  3. 使用 async/await 处理异步操作
  4. 注意服务的生命周期管理(Singleton/Transient)

优势

  1. 代码结构清晰,职责分明
  2. 便于单元测试
  3. 使用依赖注入提高代码的可维护性和可测试性
  4. 使用 CommunityToolkit.Mvvm 简化了 MVVM 模式的实现

总结

这个示例展示了如何在 WinForm 应用程序中使用 CommunityToolkit.Mvvm 和依赖注入。通过遵循 MVVM 模式,可以使代码更加清晰、可维护,同时也便于进行单元测试。虽然 WinForm 不像 WPF 那样天生支持 MVVM 模式,但通过适当的设计和工具的使用,同样可以实现清晰的分层架构。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!