[.NET/WPF] CommunityToolkit.Mvvm 异步指令

我们在开发中, 经常会有这样的需求:

  1. 点击按钮后, 进行一些耗时的工作
  2. 工作进行时, 按钮不可再次被点击
  3. 工作进行时, 会显示进度条, 或者 "加载中" 的动画

RelayCommand

CommunityToolkit.Mvvm 中的 RelayCommand 除了支持最简单的同步方法, 还支持以 Task 作为返回值的异步方法, 当我们为这样的异步方法标记上 RelayCommand 特性时, 它会生成一个对应的异步指令.

  1. 指令在执行时, 主要逻辑会在后台, 而不是运行在 UI 线程中. 具体可以参考 "异步和异步的线程切换"
  2. 指令在执行时, CanExecute 会变为 false, 此时使用该 Command 的 Button 或者其他控件, 也会变成 '被禁用' 的状态.
  3. 如果方法参数中包含一个 CancellationToken, 那么这个任务同样可以被取消. 只需要你方法内部有正确实现 "取消执行" 的逻辑就没问题.

下面是一个例子.

主窗体代码:

xml 复制代码
<Window x:Class="LearnMvvm.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:LearnMvvm"
        xmlns:vm="clr-namespace:LearnMvvm.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="7![请添加图片描述](https://img-blog.csdnimg.cn/65ddbab8f917458bbfd40ebdb6bb6d16.gif)
00">
    <Window.DataContext>
        <vm:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <StackPanel Margin="50">
            <Button Command="{Binding DoSomethingCommand}">Do something</Button>
            <Button Command="{Binding CancelDoSomethingCommand}" Margin="0 5 0 0">Cancel</Button>

            <ProgressBar Margin="0 10 0 0" Height="15" Value="{Binding Progress}"/>
        </StackPanel>
    </Grid>
</Window>

后台 ViewModel

cs 复制代码
public partial class MainViewModel : ObservableObject
{
    [ObservableProperty]
    private int progress;

    [RelayCommand]
    public async Task DoSomething(CancellationToken token)
    {
        for (int i = 0; i <= 100; i++)
        {
            if (token.IsCancellationRequested)
                return;

            await Task.Delay(100);
            Progress = i;
        }
    }

    [RelayCommand]
    public void CancelDoSomething()
    {
        DoSomethingCommand.Cancel();
    }
}

效果:

在 CommunityToolkit.Mvvm 中, 支持以下样式的 RelayCommand 签名:

  • void 方法名() 无参同步指令
  • void 方法名(类型 参数名) 有参同步指令
  • Task 方法名(), 无参, 不支持取消的异步指令
  • Task 方法名(类型 参数名) 有参, 不支持取消的异步指令
  • Task 方法名(CancellationToken token) 无参, 支持取消的异步指令
  • Task 方法名(类型 参数名, CancellationToken token) 有参, 支持取消的异步指令
相关推荐
牛哇网络工作室10 小时前
UnityHDRP写实数字人全流程基础5—语音输入和语音识别
android·unity·c#·游戏引擎·aigc·语音识别·xcode
zlinear数据采集卡20 小时前
数据采集卡从入门到精通(9):分辨率与精度——16位卡不等于1/65536的精度
开发语言·数据库·fpga开发·开源·c#
深澈Vincel1 天前
我用 C# + WebView2 做了一个针对“流氓软件”的“一键清理工具“:架构实践与踩坑记录
c#
zlinear数据采集卡1 天前
数据采集卡从入门到精通(7):流水线型ADC——级级接力,高速与高精的平衡术
开发语言·arm开发·嵌入式硬件·fpga开发·c#
kingwebo'sZone1 天前
C# 根据公式计算的方法
开发语言·c#
阿部多瑞 ABU1 天前
告别手工核图:基于 .NET + MuPDFCore 的 CAD 等轴测 PDF 材料表提取与新旧版本对比实战
后端·算法·ui·pdf·c#
条形码D1 天前
DRG综合管理分析系统-目前已经支持CHS-DRG3.0
c#·drg·3.0分组器·drg分组器·chs-drg3.0分组器
Alex Gram2 天前
数据库同步工具PanguSync图文教程
java·mysql·postgresql·sqlserver·c#·数据库同步软件·数据库同步工具
头茬韭菜2 天前
第 10 篇:「Fluss 实战案例集」—— 完整解决方案与最佳实践
c#·linq·fluss
FuckPatience2 天前
WPF 给一个界面上的按钮应用同一种样式
wpf