从视图模型的构造函数

时间:2016-06-06 13:16:42

标签: c# wpf asynchronous mvvm

我在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

1 个答案:

答案 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} }对于数据绑定错误条件(如果您愿意)。