C# 在MVVM中初始化类后执行异步方法
我希望在应用程序初始化并出现主窗口后执行这些代码行:C# 在MVVM中初始化类后执行异步方法,c#,wpf,asynchronous,mvvm,C#,Wpf,Asynchronous,Mvvm,我希望在应用程序初始化并出现主窗口后执行这些代码行: if (System.IO.File.Exists("token")) { string[] startupStrings = Environment.GetCommandLineArgs(); await _myOneDrive.SilentLogIn(); IsActive = true; if (startupStrings.Length > 1 && startupStrings
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(对象参数)
命令,因为它是void
而不是任务
。此外,我无法将其更改为任务
,因为它对RelayCommand
无效。因此,我在这个循环中,真的会使用一些提示、技巧或只是指出我的错误。当我遇到类似问题并发现一个非常简单的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();
}
}
公共类AsyncRelayCommand:RelayCommand
{
私有只读函数异步执行;
公共AsyncRelayCommand(Func asyncExecute)
:base(()=>asyncExecute())
{
_asyncExecute=asyncExecute;
}
公共AsyncRelayCommand(Func asyncExecute,Action execute)
:base(执行)
{
_asyncExecute=asyncExecute;
}
公共任务ExecuteAsync()
{
返回_asyncExecute();
}
公共覆盖无效执行(对象参数)
{
_异步执行();
}
}
然后只需修改方法以返回任务,并用新创建的AsyncRelayCommand替换RelayCommand的用法。对我来说很好
请注意,带有参数的用法可能还不起作用,因此您需要对此进行一些额外的实现。对我来说,这是没有必要的。但是您应该了解基本的想法。我认为从加载的视图事件调用ViewModel的
Initialize
方法没有问题。我不认为这违反了MVVM。我同意@Euphoric。该视图是关于VM的。查看绑定到它并使用它。MVVM的目标是让VM不必担心其属性在视图中如何表示,但这并不意味着视图不应该知道如何使用VM。谢谢。它显然工作得很好。我把它带到我的壁炉前,不使用代码隐藏,但它似乎是更好的解决方案。我尝试过使用Dispatcher
,但开始得很早。在UI任务中使用codebehind绝对没有错。不要落入那个陷阱。我会建议使用Dispatcher,但我会告诉您指定一个非常低的DispatcherPriority
,以便在数据绑定完成后初始化视图模型。您是对的。它工作得很好。然而,它也可以使用简单的RelayCommand
和async void
。我的问题是如何在启动时弹出该命令或等待函数。我决定使用Loaded
事件。