在MVVM

时间:2016-08-26 09:15:33

标签: c# wpf asynchronous mvvm

我想在初始化应用程序并显示主窗口后执行这些代码行:

if (System.IO.File.Exists("token"))
{

    string[] startupStrings = Environment.GetCommandLineArgs();
    await _myOneDrive.SilentLogIn();
    IsActive = true;
    if (startupStrings.Length > 1 && startupStrings[1] == "/a")
    {
        IsWorking = true;
        IsActive = false;
        await _myOneDrive.EjectSynchroProcedure(false);
        IsActive = true;
        IsWorking = false;
        Application.Current.Shutdown();
    }
}

不幸的是我无法做到这一点,因为我无法在我的MVVM模型构造函数中使用await运算符。注册Loaded事件会破坏MVVM的整体思路。我已经读过一般不使用async void但只是在事件处理程序的逻辑等价物中。所以我的异步命令看起来像这样:

async void SilentLogin(object parameter)
{
    await _myOneDrive.SilentLogin();
    IsActive = true;
}

然后我在构造函数中初始化它们并将命令绑​​定到XAML代码中的按钮。

public MainWindowViewModel()
{
    _myOneDrive = new MyOneDriveClient(PathPcDirectory, PathOneDriveDirectory, this);
    LoginCommand = new RelayCommand(Login);
    SilentLoginCommand = new RelayCommand(SilentLogin);
    Console = "Program started";
}

它工作得很好,但我仍然无法完成初始化后运行代码的目标。我无法等待async void Login(object parameter)命令,因为它void不是Task。更重要的是,我无法将其更改为Task,因为它对RelayCommand无效。所以我在这个循环中,并且会真正使用一些提示,技巧或指出我的错误。

1 个答案:

答案 0 :(得分:0)

当我遇到类似的问题时,我发现了一个非常简单的AsyncRelayCommand实现。

public class AsyncRelayCommand : RelayCommand
{
    private readonly Func<Task> _asyncExecute;

    public AsyncRelayCommand(Func<Task> asyncExecute)
        : base(() => asyncExecute())
    {
        _asyncExecute = asyncExecute;
    }

    public AsyncRelayCommand(Func<Task> asyncExecute, Action execute)
        : base(execute)
    {
        _asyncExecute = asyncExecute;
    }

    public Task ExecuteAsync()
    {
        return _asyncExecute();
    }

    public override void Execute(object parameter)
    {
        _asyncExecute();
    }
}

然后只需修改您的方法以返回Task,并用新创建的AsyncRelayCommand替换RelayCommand的用法。工作得很好。

请注意,参数的使用可能还没有成功,所以你需要一些额外的实现。对于我的情况,这是没有必要的。但是你应该得到基本的想法。