编辑
2025-11-25
C#
00

目录

核心组件
主要异步命令类型
异步命令特性
实战示例
基础项目设置
示例ViewModel
带取消功能的高级示例
WinForm界面实现
总结

CommunityToolkit.Mvvm提供了强大的异步编程支持,通过IAsyncRelayCommandAsyncRelayCommand等类型,使得在MVVM架构中处理异步操作变得简单而优雅。本文将详细介绍如何在WinForm应用中使用这些特性。

核心组件

主要异步命令类型

  • IAsyncRelayCommand - 异步命令接口
  • AsyncRelayCommand - 基础异步命令实现
  • AsyncRelayCommand<T> - 带参数的异步命令实现

异步命令特性

  • 自动管理执行状态
  • 取消操作支持
  • 异常处理
  • 执行状态追踪

实战示例

基础项目设置

首先创建一个WinForm项目,添加必要的NuGet包:

XML
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />

image.png

示例ViewModel

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using static System.Windows.Forms.VisualStyles.VisualStyleElement; namespace App13 { // ObservableObject 是 CommunityToolkit.Mvvm 提供的基础 ViewModel 类 public partial class MainViewModel : ObservableObject { // 使用 ObservableProperty 特性自动实现属性通知 [ObservableProperty] private string status = "就绪"; [ObservableProperty] private bool isLoading; // 异步命令 - 基础示例 private readonly IAsyncRelayCommand loadDataCommand; public IAsyncRelayCommand LoadDataCommand => loadDataCommand; public MainViewModel() { // 初始化异步命令 loadDataCommand = new AsyncRelayCommand(LoadDataAsync); } // 模拟异步数据加载 private async Task LoadDataAsync() { try { IsLoading = true; Status = "正在加载数据..."; // 模拟耗时操作 await Task.Delay(2000); Status = "数据加载完成!"; } catch (Exception ex) { MessageBox.Show($"发生错误:{ex.Message}"); Status = "加载失败"; } finally { IsLoading = false; } } } }

带取消功能的高级示例

C#
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; namespace App13 { public partial class AdvancedViewModel : ObservableObject { [ObservableProperty] private string progressStatus = "就绪"; [ObservableProperty] private int progressValue; // 使用 CancellationTokenSource 支持取消操作 private CancellationTokenSource? cts; // 声明异步命令 private readonly IAsyncRelayCommand startProcessCommand; private readonly IRelayCommand cancelCommand; public IAsyncRelayCommand StartProcessCommand => startProcessCommand; public IRelayCommand CancelCommand => cancelCommand; public AdvancedViewModel() { startProcessCommand = new AsyncRelayCommand( ExecuteLongProcessAsync, // 通过判断 cts 是否为 null 来确定命令是否可执行 () => cts == null ); cancelCommand = new RelayCommand( // 取消操作的实现 () => { cts?.Cancel(); cts = null; }, // 只有在进程运行时才能取消 () => cts != null ); } private async Task ExecuteLongProcessAsync() { try { // 创建新的 CancellationTokenSource cts = new CancellationTokenSource(); ProgressStatus = "处理中..."; ProgressValue = 0; // 模拟长时间运行的任务 for (int i = 0; i <= 100; i += 10) { // 检查是否请求取消 cts.Token.ThrowIfCancellationRequested(); ProgressValue = i; await Task.Delay(500, cts.Token); } ProgressStatus = "处理完成!"; ProgressValue = 100; } catch (OperationCanceledException) { ProgressStatus = "操作已取消"; } catch (Exception ex) { MessageBox.Show($"发生错误:{ex.Message}"); ProgressStatus = "处理失败"; } finally { cts = null; // 通知命令可用性变化 (StartProcessCommand as AsyncRelayCommand)?.NotifyCanExecuteChanged(); (CancelCommand as RelayCommand)?.NotifyCanExecuteChanged(); } } } }

WinForm界面实现

C#
namespace App13 { public partial class Form1 : Form { private readonly MainViewModel viewModel; private readonly AdvancedViewModel advancedViewModel; public Form1() { InitializeComponent(); // 初始化ViewModel viewModel = new MainViewModel(); advancedViewModel = new AdvancedViewModel(); // 设置数据绑定 SetupDataBindings(); } private void SetupDataBindings() { // 基础示例绑定 btnLoad.Click += async (s, e) => await viewModel.LoadDataCommand.ExecuteAsync(null); // 使用BindingSource实现属性绑定 var bindingSource = new BindingSource(); bindingSource.DataSource = viewModel; lblStatus.DataBindings.Add("Text", bindingSource, nameof(viewModel.Status)); // 高级示例绑定 btnStart.Click += async (s, e) => await advancedViewModel.StartProcessCommand.ExecuteAsync(null); btnCancel.Click += (s, e) => advancedViewModel.CancelCommand.Execute(null); var advancedBindingSource = new BindingSource(); advancedBindingSource.DataSource = advancedViewModel; progressBar.DataBindings.Add("Value", advancedBindingSource, nameof(advancedViewModel.ProgressValue)); lblProgressStatus.DataBindings.Add("Text", advancedBindingSource, nameof(advancedViewModel.ProgressStatus)); } } }

image.png

总结

CommunityToolkit.Mvvm提供的异步支持极大地简化了WinForm应用中的异步操作处理。通过AsyncRelayCommand和相关组件,我们可以:

  • 优雅地处理异步操作
  • 轻松实现取消功能
  • 有效管理UI状态
  • 提供良好的用户体验

合理使用这些特性,可以显著提高应用程序的响应性和用户体验。

本文作者:技术老小子

本文链接:

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