AsyncRelayCommand et AsyncRelayCommand<T>

AsyncRelayCommand et AsyncRelayCommand<T> sont des implémentations ICommand qui étendent les fonctionnalités offertes par RelayCommand, avec prise en charge des opérations asynchrones.

API de plateforme : AsyncRelayCommand, AsyncRelayCommand<T>, RelayCommand, IAsyncRelayCommand, IAsyncRelayCommand<T>

Fonctionnement

Les implémentations AsyncRelayCommand et AsyncRelayCommand<T> incluent les principales fonctionnalités suivantes :

  • Elles étendent les fonctionnalités des commandes synchrones incluses dans la bibliothèque, avec prise en charge des délégués retournant Task.
  • Elles peuvent encapsuler des fonctions asynchrones avec un paramètre CancellationToken supplémentaire pour prendre en charge l’annulation, et exposent les propriétés CanBeCanceled et IsCancellationRequested, ainsi qu’une méthode Cancel.
  • Elles exposent une propriété ExecutionTask qui peut être utilisée pour surveiller la progression d’une opération en attente, et une propriété IsRunning qui peut être utilisée pour vérifier la fin d’une opération. C’est particulièrement utile pour lier une commande à des éléments d’interface utilisateur tels que des indicateurs de chargement.
  • Elles implémentent les interfaces IAsyncRelayCommand et IAsyncRelayCommand<T>, ce qui signifie que viewmodel peut facilement exposer des commandes à l’aide de celles-ci pour réduire le couplage étroit entre les types. Par exemple, elles facilitent le remplacement d’une commande par une implémentation personnalisée exposant la même surface d’API publique, si nécessaire.

Utilisation de commandes asynchrones

Imaginons un scénario similaire à celui décrit dans l’exemple RelayCommand, mais avec une commande exécutant une opération asynchrone :

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

    public IAsyncRelayCommand DownloadTextCommand { get; }

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

Avec le code d’interface utilisateur associé :

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

Lorsque vous cliquez sur le bouton Button, la commande est appelée et la tâche ExecutionTask est mise à jour. Une fois l’opération terminée, la propriété déclenche une notification qui s’affiche dans l’interface utilisateur. Dans ce cas, l’état de la tâche et le résultat actuel de la tâche sont affichés. Notez que pour afficher le résultat de la tâche, il est nécessaire d’utiliser la méthode TaskExtensions.GetResultOrDefault qui permet d’accéder au résultat d’une tâche non encore terminée sans bloquer le thread (et éventuellement provoquer un interblocage).

Exemples

  • Consultez l’exemple d’application (pour plusieurs infrastructures d’interface utilisateur) afin de voir le Kit d’outils Modèle-vue-vue modèle (MVVM) en action.
  • Vous trouverez également d’autres exemples dans les tests unitaires.