MVVM c#如何将异步数据加载到属性中?

Kil*_*All 4 c# wpf mvvm

我想知道是否有更好的方法将异步数据加载到属性中.现在我创建一个异步函数并在属性的Get部分中引发一个Task,如下所示:

private ObservableCollection<CProyecto> prope;

public ObservableCollection<CProyecto> Prope
{
    get 
    {
        if (prope == null)
        {
            Task.Run(()=> LoadData()).Wait();
        }

        return proyectos;
    }
    set 
    { 
        prope = value; 
        RaisePropertyChanged(); 
    }
}

async private Task LoadData() 
{
    Prope = await clsStaticClassDataLoader.GetDataFromWebService();
}
Run Code Online (Sandbox Code Playgroud)

这种方法有效,但我不喜欢使用.Wait,因为如果服务没有快速响应,它可以冻结屏幕.

你能指导我这件事吗?

提前致谢

Ber*_*sch 8

我处理这个的方法是在构造对象时开始加载属性的过程,但我没有等待结果。由于该属性会在填充时发出通知,因此绑定工作得很好。本质上它是这样工作的:

public class MyClass : INotifyPropertyChanged
{
    private ObservableCollection<CProyecto> prope;

    public ObservableCollection<CProyecto> Prope
    {
        get { return prope; }
        set { prope = value; RaisePropertyChanged(nameof(Prope)); }
    }

    public MyClass()
    {
        // Don't wait or await.  When it's ready
        // the UI will get notified.
        LoadData();
    }

    async private Task LoadData() 
    {
        Prope = await clsStaticClassDataLoader.GetDataFromWebService();
    }
}
Run Code Online (Sandbox Code Playgroud)

这非常有效,并且不会在 UI 中造成任何延迟或卡顿。如果您希望该集合永远不会成为null(IMO 的一个好习惯),您可以prope使用一个空集合预先初始化该字段。

  • 这是一个很好的第一步,但会默默地吞下“LoadData”抛出的错误。更全面的方法是在 LoadData 中有一个顶级的 try/catch 并使用错误通知更新您的 UI。 (4认同)
  • 同意。我正在描述我采取的_方法_。但是,您有正确的位置来进行错误处理。 (2认同)

Ste*_*ary 7

我建议你阅读关于异步MVVM数据绑定的 MSDN文章.我有一个提供NotifyTask<T>类型的库,可以这样使用:

public class MyClass : INotifyPropertyChanged
{
  public NotifyTask<ObservableCollection<CProyecto>> Prope { get; private set; }

  public MyClass()
  {
    // Synchronously *start* the operation.
    Prope = NotifyTask.Create(LoadDataAsync());
  }

  async private Task<ObservableCollection<CProyecto>> LoadDataAsync()
  {
    return await clsStaticClassDataLoader.GetDataFromWebService();
  }
}
Run Code Online (Sandbox Code Playgroud)

然后您的数据绑定将继续运行Prope.Result.

这种方法的优点是您还可以使用数据绑定来隐藏/显示繁忙指示符(Prope.IsNotCompleted),在数据可用时显示控件(Prope.IsSuccessfullyCompleted)和错误通知(Prope.IsFaulted/ Prope.ErrorMessage).

此外,null如果您愿意,可以指定非默认值:

Prope = NotifyTask.Create(LoadDataAsync(), new ObservableCollection<CProyecto>());
Run Code Online (Sandbox Code Playgroud)