我正在使用MVVM和WPF,现在我从我的viewmodel类的构造函数中调用async进程,如下所示:
Task.Run(() => this.MyMetho(someParam)).Wait();
这个问题是屏幕冻结它直到任务结束。
另一种方法是在ViewModel中创建LoadDataMethod
并从UserControl_Loaded
的事件处理程序中的视图中调用它
private async void UserControl_Loaded(object sender, RoutedEventArgs e)
{
VMRep vm = (VMRep)this.DataContext;
await vm.LoadDataMethod();
}
这种方式效果更好,但我想有一种更好的方法来为视图加载异步数据。
感谢您的评论
答案 0 :(得分:1)
您可以创建异步工厂方法,并使您的构造函数成为私有或受保护的
public static async bool Create() {
var control = new UserControl();
return await LoadDataMethod();
}
答案 1 :(得分:1)
我想有更好的方法来加载View的异步数据
关键是要意识到所有ViewModel必须立即初始化 。如果您考虑一下,将它们异步初始化是没有意义的,因为当WPF构建您的VM时,它必须立即显示它。从下载完成后不到10秒。
所以,转移一下你的想法,答案会变得更加清晰。您的VM需要立即初始化,但您还没有要显示的数据。因此,适当的做法是立即初始化为一种“加载...”状态,并启动下载数据。当数据到达时,您更新 VM以显示数据。
你可以按照你拥有它的方式去做:
private async void UserControl_Loaded(object sender, RoutedEventArgs e)
{
VMRep vm = (VMRep)this.DataContext;
await vm.LoadDataMethod();
}
但这并没有为View提供一种干净的方法来检测数据是否正在加载或已完成加载。我写了一个data-bindable Task<T>
wrapper(更新版本here)来帮助解决这种情况。它可以像这样使用:
public MyViewModel()
{
MyData = NotifyTask.Create(LoadDataAsync());
}
public NotifyTask<TMyData> MyData { get; }
然后您的View可以数据绑定到MyData.Result
以获取数据,以及其他属性(例如MyData.IsNotCompleted
)来显示/隐藏“加载”指示符。
答案 2 :(得分:0)
好吧,既然我不确切知道你想要完成什么,我会尽力给你一个关于Lazy的简要解释
private Lazy<Task<string>> getInfo;
在这种情况下,我会在您的情况下持有Lazy<Task<string>>
的字段Lazy<Task<VMRep>>
。我正在使用这个字段,所以你可以在课堂上调用这个懒惰的initialzier。
public Laziness()
{
this.getInfo = new Lazy<Task<string>>(async () => await this.GetInfo());
}
在构造函数中,我将值赋给惰性字段。在这种情况下使用方法GetInfo()
public string GetLazyInfo
{
get
{
return this.getInfo.Value.Result;
}
}
使用公共属性公开getInfo
字段。并从惰性内部的任务返回结果。
private async Task<string> GetInfo()
{
await Task.Run(async () => await Task.Delay(5000));
return await Task.Run(() => "test");
}
最后是你的魔法可以发生的方法。