我在Visual Studio 2015中使用Entity Framework 6构建MVVM Light WPF应用程序。该应用程序有许多视图模型,可以调用async
方法进行初始化。这是一个示例视图模型:
public class MyViewModel : MyViewModelBase
{
public MyViewModel()
{
PopulateParameters();
// Other code...
}
public ObservableCollection<ParametersViewModel>
Parameters { get; private set; } =
new ObservableCollection<ParametersViewModel>();
private async void PopulateParameters()
{
var service = new MyDataService();
Parameters.Clear();
foreach(var parameter in await service.GetParameters())
Parameters.Add(parameter);
}
// Other methods and properties
}
在MyDataService
课程中,我有这个方法:
public async Task<ParametersViewModel> GetParameters()
{
using (var context = new MyEntities())
{
var query = (from param in context.Parameters
select new ParametersViewModel
{
// Populate ParametersViewModel properties here...
}
);
return await Task.Run(() => query);
}
}
请注意,视图模型的构造函数正在调用async void
方法PopulateParameters()
。这是非常糟糕的编程,我想改变它。但是,我不确定如何。我无法将所需的数据注入到我的所有视图模型中;有些人必须执行自己的初始化,其中大部分涉及对async
方法的调用。
当从视图模型的构造函数调用异步方法时,如何更改上述代码以符合最佳实践?感谢。
更新:确保绑定到.Result
返回的值的NotifyTask.Create()
。我花了一段时间来弄清楚这一点。更多相关内容:https://msdn.microsoft.com/en-us/magazine/dn605875.aspx
答案 0 :(得分:3)
我有一篇博客文章介绍了“async constructors”的几种方法。
在这种情况下,看起来你真正想要的是async data binding。使用Mvvm.Async library中的NotifyTask
类型将如下所示:
public NotifyTask<ObservableCollection<ParametersViewModel>>
Parameters { get; private set { /* with notify, such as RaisePropertyChanged() */ } }
public MyViewModel()
{
Parameters = NotifyTask.Create(() => GetParametersAsync(),
new ObservableCollection<ParametersViewModel>());
// Other code...
}
private async Task<ObservableCollection<ParametersViewModel>> GetParametersAsync()
{
var service = new MyDataService();
var result = new ObservableCollection<ParametersViewModel>();
foreach(var parameter in await service.GetParameters())
result.Add(parameter);
return result;
}
NotifyTask<T>
包装器提供了几个可绑定数据的属性,例如包含可观察集合的Result
,用于显示加载指示符的IsNotCompleted
,以及IsFaulted
/ {{1} }对于数据绑定错误条件(如果您愿意)。