等待具有或不具有异步Action的Command.Execute

问题描述 投票:0回答:1

我遇到了一个奇怪的案子,我被困在上面。

我有一个Popup View + ViewModel作为一个按钮。 Popup从其他视图获取Command以执行按钮。

现在,我想在单击后立即禁用该按钮,运行该命令然后禁用它。

这就是我现在拥有的:

PopupViewModel

public override Task InitializeAsync(object navigationData)
{
    PopupModel model = (PopupModel) navigationData;
    ...
    _mainActionCommandToRun = model.MainActionCommand;
    ...
    return base.InitializeAsync(navigationData);
}

private void OnMainActionCommand(object obj)
{
    MainActionCommand.CanExecute(false);
    _mainActionCommandToRun.Execute(null);
    MainActionCommand.CanExecute(true);
}

一些查看如何使用弹出窗口

await DialogService.ShowPopupAsync<PopupViewModel>(new PopupModel
{
    ...
    MainActionCommand = new Command(
        () =>
        {
            DoSomeThing();
        })
});

这个案子就像一个魅力。分配给命令的操作是异步时,它会变得复杂。

一些具有异步操作的视图

await DialogService.ShowPopupAsync<PopupViewModel>(new PopupModel
{
    ...
    MainActionCommand = new Command(
       async () =>
        {
            await DoSomeThing();
        })
});

在这种情况下,_mainActionCommandToRun.Execute(null)将触发异步操作并继续执行CanExecute(true)。

我无法等待执行,因为它是一个void方法,用任务包装它不会解决任何问题......

基本上,我有一个异步方法,不知道它是一个异步方法。

c# multithreading xamarin.forms command
1个回答
0
投票

你需要一些asynchronous command的概念。如今,一些MVVM库内置了这个:

public interface IAsyncCommand : ICommand
{
  Task ExecuteAsync(object parameter);
}

ICommand.Execute实施总是async void ICommand.Execute(object parameter) => await ExecuteAsync(parameter)。然后你可以定义你自己的AsyncCommand,就像Command一样,除了它实现了IAsyncCommand

然后让你的视图模型公开IAsyncCommand而不是ICommand,你的弹出逻辑可以使用:

private async void OnMainActionCommand(object obj)
{
  MainActionCommand.CanExecute(false);
  await _mainActionCommandToRun.ExecuteAsync(null);
  MainActionCommand.CanExecute(true);
}
© www.soinside.com 2019 - 2024. All rights reserved.