AsyncRelayCommand und AsyncRelayCommand<T>
Bei AsyncRelayCommand
und AsyncRelayCommand<T>
handelt es sich um ICommand
-Implementierungen, die die von RelayCommand
angebotenen Funktionalitäten erweitern und asynchrone Operationen unterstützen.
Plattform APIs:
AsyncRelayCommand
,AsyncRelayCommand<T>
,RelayCommand
,IAsyncRelayCommand
,IAsyncRelayCommand<T>
Funktionsweise
AsyncRelayCommand
und AsyncRelayCommand<T>
haben die folgenden Hauptfunktionen:
- Sie erweitern die Funktionalitäten der in der Bibliothek enthaltenen synchronen Befehle um die Unterstützung von Delegaten mit
Task
-Rückgabe. - Sie können asynchrone Funktionen mit einem zusätzlichen
CancellationToken
-Parameter verpacken, um einen Abbruch zu unterstützen, und sie stellen eineCanBeCanceled
- undIsCancellationRequested
-Eigenschaft sowie eineCancel
-Methode zur Verfügung. - Sie stellen eine
ExecutionTask
-Eigenschaft zur Verfügung, mit der der Fortschritt einer anstehenden Operation überwacht werden kann, und eineIsRunning
-Eigenschaft, mit der überprüft werden kann, wann eine Operation abgeschlossen ist. Dies ist besonders nützlich, um einen Befehl an Benutzeroberflächenelemente wie Ladeanzeigen zu binden. - Sie implementieren die
IAsyncRelayCommand
- undIAsyncRelayCommand<T>
-Schnittstellen, was bedeutet, dass das ViewModel Befehle mit Hilfe dieser Schnittstellen leicht offenlegen kann, um die enge Kopplung zwischen den Typen zu verringern. Dies macht es zum Beispiel einfacher, einen Befehl durch eine benutzerdefinierte Implementierung zu ersetzen, die dieselbe öffentliche API-Oberfläche aufweist, falls erforderlich.
Arbeiten mit asynchronen Befehlen
Stellen wir uns ein ähnliches Szenario vor wie das im RelayCommand
-Beispiel beschriebene, aber ein Befehl, der eine asynchrone Operation ausführt:
public class MyViewModel : ObservableObject
{
public MyViewModel()
{
DownloadTextCommand = new AsyncRelayCommand(DownloadText);
}
public IAsyncRelayCommand DownloadTextCommand { get; }
private Task<string> DownloadText()
{
return WebService.LoadMyTextAsync();
}
}
Mit dem zugehörigen Code für die Benutzeroberfläche:
<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>
Beim Klicken auf den Befehl Button
wird der Befehl aufgerufen und ExecutionTask
wird aktualisiert. Wenn der Vorgang abgeschlossen ist, löst die Eigenschaft eine Benachrichtigung aus, die in der Benutzeroberfläche angezeigt wird. In diesem Fall werden sowohl der Status der Aufgabe als auch das aktuelle Ergebnis der Aufgabe angezeigt. Um das Ergebnis der Aufgabe anzuzeigen, muss die TaskExtensions.GetResultOrDefault
-Methode verwendet werden. Sie ermöglicht den Zugriff auf das Ergebnis einer Aufgabe, die noch nicht abgeschlossen ist, ohne den Thread zu blockieren (und möglicherweise einen Deadlock zu verursachen).
Beispiele
- Sehen Sie sich die Beispiel-App (für mehrere Benutzeroberflächen-Frameworks) an, um das MVVM-Toolkit in Aktion zu sehen.
- Weitere Beispiele finden Sie auch in den Komponententests.