Поделиться через


AsyncRelayCommand и AsyncRelayCommand<T>

ICommand AsyncRelayCommand<T> РеализацииAsyncRelayCommand, расширяющие функциональные возможности, предоставляемые RelayCommandс поддержкой асинхронных операций.

API платформы: AsyncRelayCommand, AsyncRelayCommand<T>, RelayCommandIAsyncRelayCommandIAsyncRelayCommand<T>

Принцип работы

AsyncRelayCommand и AsyncRelayCommand<T> имеют следующие основные функции:

  • Они расширяют функциональные возможности синхронных команд, включенных в библиотеку, с поддержкой Taskвозвращающих делегатов.
  • Они могут упаковать асинхронные функции с дополнительным CancellationToken параметром для поддержки отмены, а также предоставлять CanBeCanceled свойства и IsCancellationRequested свойства, а также Cancel метод.
  • Они предоставляют ExecutionTask свойство, которое можно использовать для мониторинга хода выполнения ожидающей операции, и IsRunning можно использовать для проверки завершения операции. Это особенно полезно для привязки команды к элементам пользовательского интерфейса, таким как индикаторы загрузки.
  • Они реализуют IAsyncRelayCommand интерфейсы и IAsyncRelayCommand<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();
    }
}

С соответствующим кодом пользовательского интерфейса:

<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 обновляется. После завершения операции свойство вызывает уведомление, которое отражается в пользовательском интерфейсе. В этом случае отображаются состояние задачи и текущий результат задачи. Обратите внимание, что для отображения результата задачи необходимо использовать TaskExtensions.GetResultOrDefault метод . Это обеспечивает доступ к результату задачи, которая еще не завершена, не блокируя поток (и, возможно, вызывая взаимоблокировку).

Примеры

  • Ознакомьтесь с примером приложения (для нескольких платформ пользовательского интерфейса), чтобы просмотреть набор средств MVVM в действии.
  • Дополнительные примеры можно найти в модульных тестах.