CommunityToolkit.Mvvm提供了強(qiáng)大的異步編程支持,通過IAsyncRelayCommand
和AsyncRelayCommand
等類型,使得在MVVM架構(gòu)中處理異步操作變得簡(jiǎn)單而優(yōu)雅。本文將詳細(xì)介紹如何在WinForm應(yīng)用中使用這些特性。
核心組件
主要異步命令類型
IAsyncRelayCommand
AsyncRelayCommand
- 基礎(chǔ)異步命令實(shí)現(xiàn)AsyncRelayCommand
- 帶參數(shù)的異步命令實(shí)現(xiàn)
異步命令特性
- 自動(dòng)管理執(zhí)行狀態(tài)
- 取消操作支持
- 異常處理
- 執(zhí)行狀態(tài)追蹤
實(shí)戰(zhàn)示例
基礎(chǔ)項(xiàng)目設(shè)置
首先創(chuàng)建一個(gè)WinForm項(xiàng)目,添加必要的NuGet包:
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
?
示例ViewModel
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
usingstatic System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace App13
{
// ObservableObject 是 CommunityToolkit.Mvvm 提供的基礎(chǔ) ViewModel 類
public partial class MainViewModel : ObservableObject
{
// 使用 ObservableProperty 特性自動(dòng)實(shí)現(xiàn)屬性通知
[ObservableProperty]
privatestring status = "就緒";
[ObservableProperty]
privatebool isLoading;
// 異步命令 - 基礎(chǔ)示例
private readonly IAsyncRelayCommand loadDataCommand;
public IAsyncRelayCommand LoadDataCommand => loadDataCommand;
public MainViewModel()
{
// 初始化異步命令
loadDataCommand = new AsyncRelayCommand(LoadDataAsync);
}
// 模擬異步數(shù)據(jù)加載
private async Task LoadDataAsync()
{
try
{
IsLoading = true;
Status = "正在加載數(shù)據(jù)...";
// 模擬耗時(shí)操作
await Task.Delay(2000);
Status = "數(shù)據(jù)加載完成!";
}
catch (Exception ex)
{
MessageBox.Show($"發(fā)生錯(cuò)誤:{ex.Message}");
Status = "加載失敗";
}
finally
{
IsLoading = false;
}
}
}
}
帶取消功能的高級(jí)示例
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]
privatestring progressStatus = "就緒";
[ObservableProperty]
privateint 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 來確定命令是否可執(zhí)行
() => cts == null
);
cancelCommand = new RelayCommand(
// 取消操作的實(shí)現(xiàn)
() =>
{
cts?.Cancel();
cts = null;
},
// 只有在進(jìn)程運(yùn)行時(shí)才能取消
() => cts != null
);
}
private async Task ExecuteLongProcessAsync()
{
try
{
// 創(chuàng)建新的 CancellationTokenSource
cts = new CancellationTokenSource();
ProgressStatus = "處理中...";
ProgressValue = 0;
// 模擬長(zhǎng)時(shí)間運(yùn)行的任務(wù)
for (int i = 0; i <= 100; i += 10)
{
// 檢查是否請(qǐng)求取消
cts.Token.ThrowIfCancellationRequested();
ProgressValue = i;
await Task.Delay(500, cts.Token);
}
ProgressStatus = "處理完成!";
ProgressValue = 100;
}
catch (OperationCanceledException)
{
ProgressStatus = "操作已取消";
}
catch (Exception ex)
{
MessageBox.Show($"發(fā)生錯(cuò)誤:{ex.Message}");
ProgressStatus = "處理失敗";
}
finally
{
cts = null;
// 通知命令可用性變化
(StartProcessCommand as AsyncRelayCommand)?.NotifyCanExecuteChanged();
(CancelCommand as RelayCommand)?.NotifyCanExecuteChanged();
}
}
}
}
WinForm界面實(shí)現(xiàn)
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();
// 設(shè)置數(shù)據(jù)綁定
SetupDataBindings();
}
private void SetupDataBindings()
{
// 基礎(chǔ)示例綁定
btnLoad.Click += async (s, e) => await viewModel.LoadDataCommand.ExecuteAsync(null);
// 使用BindingSource實(shí)現(xiàn)屬性綁定
var bindingSource = new BindingSource();
bindingSource.DataSource = viewModel;
lblStatus.DataBindings.Add("Text", bindingSource, nameof(viewModel.Status));
// 高級(jí)示例綁定
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));
}
}
}

總結(jié)
CommunityToolkit.Mvvm提供的異步支持極大地簡(jiǎn)化了WinForm應(yīng)用中的異步操作處理。通過AsyncRelayCommand
和相關(guān)組件,我們可以:
- 優(yōu)雅地處理異步操作
- 輕松實(shí)現(xiàn)取消功能
- 有效管理UI狀態(tài)
- 提供良好的用戶體驗(yàn)
合理使用這些特性,可以顯著提高應(yīng)用程序的響應(yīng)性和用戶體驗(yàn)。
該文章在 2025/3/14 9:44:27 編輯過