AsyncRelayCommand i AsyncRelayCommand<T>

AsyncRelayCommand i AsyncRelayCommand<T> to implementacje ICommand, które rozszerzają funkcjonalności oferowane przez RelayCommand, o obsługę operacji asynchronicznych.

Interfejsy API platformy:AsyncRelayCommand, , AsyncRelayCommand<T>RelayCommand, , IAsyncRelayCommandIAsyncRelayCommand<T>

Jak działają

AsyncRelayCommand i AsyncRelayCommand<T> mają następujące główne funkcje:

  • Rozszerzają funkcjonalność synchronicznych poleceń zawartych w bibliotece, dodając obsługę delegatów zwracających Task.
  • Mogą opakować funkcje asynchroniczne dodatkowym parametrem CancellationToken, aby obsługiwać anulowanie, a także udostępniają właściwości CanBeCanceled i IsCancellationRequested, jak również metodę Cancel.
  • Udostępniają właściwość ExecutionTask, której można używać do monitorowania postępu trwającej operacji, oraz element IsRunning, którego można używać do sprawdzenia, kiedy operacja się zakończy. Jest to szczególnie przydatne w przypadku powiązania polecenia z elementami interfejsu użytkownika, takimi jak wskaźniki ładowania.
  • Implementują interfejsy IAsyncRelayCommand i IAsyncRelayCommand<T>, co oznacza, że model widoku może łatwo udostępniać polecenia za ich pomocą, aby zmniejszyć ścisłe powiązanie między typami. Na przykład ułatwia to zastąpienie polecenia niestandardową implementacją uwidacznianą w razie potrzeby tę samą publiczną powierzchnię interfejsu API.

Praca z poleceniami asynchronicznymi

Wyobraźmy sobie scenariusz podobny do scenariusza opisanego w przykładzie RelayCommand , ale polecenie wykonujące operację asynchroniczną:

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

    public IAsyncRelayCommand DownloadTextCommand { get; }

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

Za pomocą powiązanego kodu interfejsu użytkownika:

<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>

Po kliknięciu elementu Button polecenie zostaje wykonane, a element ExecutionTask zostaje zaktualizowany. Po zakończeniu operacji właściwość zgłasza powiadomienie, które jest odzwierciedlone w interfejsie użytkownika. W takim przypadku są wyświetlane zarówno stan zadania, jak i bieżący wynik zadania. Należy pamiętać, że aby pokazać wynik zadania, konieczne jest użycie TaskExtensions.GetResultOrDefault metody — zapewnia to dostęp do wyniku zadania, które nie zostało jeszcze ukończone bez blokowania wątku (i ewentualnie powoduje zakleszczenie).

Przykłady

  • Zapoznaj się z przykładową aplikacją (dla wielu struktur interfejsu użytkownika), aby zobaczyć, jak działa zestaw narzędzi MVVM Toolkit.
  • Więcej przykładów można również znaleźć w testach jednostkowych.