分类
标签
.NET 9008 adb android apt asp.net ASP.NET Core audio bug C c++ C++ chrome cmd csharp CSharp css css3 debian debug dotnet dotnet Framework dpkg GDI&GDI+ gdi&gdi+ golang graphics html html5 http java javascript json kali linux linux mci microsoft minimap MSBuild mysql OpenCV PInvoke powershell python QQ rust shell speex sql tutorial ubuntu ui unity vb.net visual studio Visual Studio web Web win32 winapi windows winform WinForm wpf WPF xaml xfce 列表 刷机 前端 加密 反射 反编译 可视化 图像处理 多线程 字符串 安卓 实例 局域网 幻影坦克 库 开发语言 异步 微信 手册 手机 接口 摘要 救砖 数字签名 数字证书 数字音频 数据库 桌面程序 游戏 游戏引擎 源码 爬虫 玩游戏 电脑硬件 笔记 算法 类库 线性代数 编程语言 网络 脚本语言 计算机图形学 计算机基础 设计模式 语音编解码 运维 进制 面向对象编程 音频 音频编码解码
487 字
2 分钟
[.NET/WPF] CommunityToolkit.Mvvm 异步指令
我们在开发中, 经常会有这样的需求:
- 点击按钮后, 进行一些耗时的工作
- 工作进行时, 按钮不可再次被点击
- 工作进行时, 会显示进度条, 或者 “加载中” 的动画
RelayCommand
CommunityToolkit.Mvvm 中的 RelayCommand 除了支持最简单的同步方法, 还支持以 Task 作为返回值的异步方法, 当我们为这样的异步方法标记上 RelayCommand
特性时, 它会生成一个对应的异步指令.
- 指令在执行时, 主要逻辑会在后台, 而不是运行在 UI 线程中. 具体可以参考 “异步和异步的线程切换”
- 指令在执行时, CanExecute 会变为 false, 此时使用该 Command 的 Button 或者其他控件, 也会变成 ‘被禁用’ 的状态.
- 如果方法参数中包含一个
CancellationToken
, 那么这个任务同样可以被取消. 只需要你方法内部有正确实现 “取消执行” 的逻辑就没问题.
下面是一个例子.
主窗体代码:
<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![请添加图片描述](/images/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
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)
有参, 支持取消的异步指令
[.NET/WPF] CommunityToolkit.Mvvm 异步指令
https://slimenull.com/posts/20230818143649/