Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Os AsyncRelayCommand e AsyncRelayCommand<T> são ICommand implementações que estendem as funcionalidades oferecidas por RelayCommand, com suporte para operações assíncronas.
APIs da plataforma:
AsyncRelayCommand,AsyncRelayCommand<T>,RelayCommand,IAsyncRelayCommand,IAsyncRelayCommand<T>
Como funcionam
AsyncRelayCommand e AsyncRelayCommand<T> têm as seguintes características principais:
- Estendem as funcionalidades dos comandos síncronos incluídos na biblioteca, com suporte para delegados que devolvem
Task. - Podem envolver funções assíncronas com um parâmetro adicional
CancellationTokenpara suportar cancelamento, e expõem as propriedadesCanBeCanceledeIsCancellationRequested, bem como um métodoCancel. - Eles expõem uma
ExecutionTaskpropriedade que pode ser usada para monitorizar o progresso de uma operação pendente, eIsRunningque pode ser usada para verificar quando uma operação termina. Isto é particularmente útil para associar um comando a elementos da interface, como indicadores de carregamento. - Implementam as interfaces
IAsyncRelayCommandeIAsyncRelayCommand<T>, o que significa que o modelo de vista pode expor facilmente comandos através delas para reduzir o acoplamento forte entre tipos. Por exemplo, isto facilita substituir um comando por uma implementação personalizada que expõe a mesma superfície pública da API, se necessário.
Trabalhar com comandos assíncronos
Vamos imaginar um cenário semelhante ao descrito no RelayCommand exemplo, mas com um comando a executar uma operação assíncrona:
public class MyViewModel : ObservableObject
{
public MyViewModel()
{
DownloadTextCommand = new AsyncRelayCommand(DownloadText);
}
public IAsyncRelayCommand DownloadTextCommand { get; }
private Task<string> DownloadText()
{
return WebService.LoadMyTextAsync();
}
}
Com o código de interface relacionado:
<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>
Ao clicar no Button, o comando é executado e o ExecutionTask é atualizado. Quando a operação termina, a propriedade gera uma notificação que é refletida na interface. Neste caso, tanto o estado da tarefa como o resultado atual da tarefa são apresentados. Note que, para mostrar o resultado da tarefa, é necessário usar o TaskExtensions.GetResultOrDefault método – isto dá acesso ao resultado de uma tarefa que ainda não foi concluída sem bloquear o thread (e possivelmente causar um deadlock).
Exemplos
- Dá uma vista de olhos à aplicação de exemplo (para múltiplos frameworks de interface) para veres o MVVM Toolkit em ação.
- Também podes encontrar mais exemplos nos testes unitários.