我想知道是否有更好的方法将异步数据加载到属性中.现在我创建一个异步函数并在属性的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,因为如果服务没有快速响应,它可以冻结屏幕.
你能指导我这件事吗?
提前致谢
我处理这个的方法是在构造对象时开始加载属性的过程,但我没有等待结果。由于该属性会在填充时发出通知,因此绑定工作得很好。本质上它是这样工作的:
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使用一个空集合预先初始化该字段。
我建议你阅读关于异步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)