AsyncRelayCommand 和 AsyncRelayCommand<T>

AsyncRelayCommandAsyncRelayCommand<T>ICommand 实现,它们扩展了 RelayCommand 提供的功能,并支持异步操作。

平台 API:AsyncRelayCommandAsyncRelayCommand<T>RelayCommandIAsyncRelayCommandIAsyncRelayCommand<T>

工作原理

AsyncRelayCommandAsyncRelayCommand<T> 具有以下主要功能:

  • 它们扩展了库中包含的同步命令的功能,并支持 Task 返回委托。
  • 它们可以使用附加 CancellationToken 参数包装异步函数以支持取消,并公开 CanBeCanceledIsCancellationRequested 属性以及 Cancel 方法。
  • 它们公开可用于监视挂起操作进度的 ExecutionTask 属性,以及可用于检查操作完成时间的 IsRunning 属性。 这对于将命令绑定到 UI 元素(如加载指示器)特别有用。
  • 它们实现 IAsyncRelayCommandIAsyncRelayCommand<T> 接口,这意味着 viewmodel 可以轻松地使用这些接口来公开命令,从而减少类型之间的紧密耦合。 例如,这样就可以轻松地将命令替换为公开相同公共 API 图面的自定义实现(如果需要)。

使用异步命令

假设一个方案类似于 RelayCommand 示例中所述的方案,但命令执行异步操作:

public class MyViewModel : ObservableObject
{
    public MyViewModel()
    {
        DownloadTextCommand = new AsyncRelayCommand(DownloadText);
    }

    public IAsyncRelayCommand DownloadTextCommand { get; }

    private Task<string> DownloadText()
    {
        return WebService.LoadMyTextAsync();
    }
}

使用相关的 UI 代码:

<Page
    x:Class="MyApp.Views.MyPage"
    xmlns:viewModels="using:MyApp.ViewModels"
    xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters">
    <Page.DataContext>
        <viewModels:MyViewModel x:Name="ViewModel"/>
    </Page.DataContext>
    <Page.Resources>
        <converters:TaskResultConverter x:Key="TaskResultConverter"/>
    </Page.Resources>

    <StackPanel Spacing="8" xml:space="default">
        <TextBlock>
            <Run Text="Task status:"/>
            <Run Text="{x:Bind ViewModel.DownloadTextCommand.ExecutionTask.Status, Mode=OneWay}"/>
            <LineBreak/>
            <Run Text="Result:"/>
            <Run Text="{x:Bind ViewModel.DownloadTextCommand.ExecutionTask, Converter={StaticResource TaskResultConverter}, Mode=OneWay}"/>
        </TextBlock>
        <Button
            Content="Click me!"
            Command="{x:Bind ViewModel.DownloadTextCommand}"/>
        <ProgressRing
            HorizontalAlignment="Left"
            IsActive="{x:Bind ViewModel.DownloadTextCommand.IsRunning, Mode=OneWay}"/>
    </StackPanel>
</Page>

单击 Button 时,将调用该命令并更新 ExecutionTask。 操作完成后,该属性将引发一个通知,该通知反映在 UI 中。 在这种情况下,将同时显示任务状态和当前任务结果。 请注意,若要显示任务的结果,则必须使用 TaskExtensions.GetResultOrDefault 方法 - 这样就可以无需阻止线程(可能导致死锁)即可访问尚未完成的任务的结果。

示例

  • 查看示例应用(适用于多个 UI 框架),以了解 MVVM 工具包的实际运行情况。
  • 还可以在单元测试中查找更多示例。