C# 异步加载ViewModel中的数据(使用async和await)而不使用数据绑定
我用默认模板启动了一个手机应用程序,该模板已经定义了一个视图模型。我修改了MainViewModel的LoadData()方法,以异步调用odata服务。但它不适用于数据绑定。我已验证呼叫已成功返回,但未显示结果 LongListSelector的items源绑定到视图模型中的items属性C# 异步加载ViewModel中的数据(使用async和await)而不使用数据绑定,c#,data-binding,mvvm,windows-phone-8,async-await,C#,Data Binding,Mvvm,Windows Phone 8,Async Await,我用默认模板启动了一个手机应用程序,该模板已经定义了一个视图模型。我修改了MainViewModel的LoadData()方法,以异步调用odata服务。但它不适用于数据绑定。我已验证呼叫已成功返回,但未显示结果 LongListSelector的items源绑定到视图模型中的items属性 <phone:LongListSelector ItemsSource="{Binding Items}" x:Name="MainLongListSelector" Margin="0,0,-12,
<phone:LongListSelector ItemsSource="{Binding Items}" x:Name="MainLongListSelector" Margin="0,0,-12,0" SelectionChanged="MainLongListSelector_SelectionChanged">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding UnReadCount}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding description}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
一走了之,什么也没出现……我错过了什么吗?非常感谢任何指针。好的,快速的回答是您可能缺少
项目和/或IsDataLoaded
设置器上的INotifyPropertyChanged
通知
较长的答案需要一点时间。:)
首先,应该避免async void
。我在文章中详细描述了原因。在这种情况下,考虑错误处理。令人高兴的是,当“呼叫成功返回”时,您的快乐案例是很好的,但悲伤的案例将撕毁您的程序
因此,让我们尽可能地将所有内容重写为异步任务
,同时:
public async Task LoadDataAsync()
{
await FetchTileViewItemsAsync();
}
private async Task FetchTileViewItemsAsync()
{
var ret = await I2ADataServiceHelper.GetTileViewItemsAsync();
this.Items = new ObservableCollection<TileViewItem>(ret);
this.IsDataLoaded = true;
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
await App.ViewModel.LoadDataAsync();
}
}
但实际上,我更倾向于以ViewModel为中心、数据绑定友好的错误处理系统。这样,“断开连接”对于应用程序来说是一种非常自然的状态;即使它所做的只是显示一条错误消息,您的应用程序最终也是为偶尔连接的系统(即电话)设计的。此外,生成的代码更易于测试
我在几篇博客文章中描述了这种方法:我在async
构造函数的文章中介绍了,在async
属性的文章中介绍了。我编写了一个名为的helper类,它使您能够对数据绑定使用Task
将这些设计放置到位后,ViewModel代码最终看起来更像这样:
public sealed class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<TileViewItem> Items
{
get { return _items; }
private set { _items = value; RaisePropertyChanged(); }
}
public ITaskCompletionNotifier Initialization { get; private set; }
public MyViewModel()
{
Initialization = TaskCompletionNotifierFactory.Create(InitializeAsync());
}
private async Task InitializeAsync()
{
var ret = await I2ADataServiceHelper.GetTileViewItemsAsync();
this.Items = new ObservableCollection<TileViewItem>(ret);
}
}
公共密封类MyViewModel:INotifyPropertyChanged
{
公共可观测收集项目
{
获取{return\u items;}
私有集{u items=value;RaisePropertyChanged();}
}
公共ITaskCompletionNotifier初始化{get;private set;}
公共MyViewModel()
{
Initialization=TaskCompletionNotifierFactory.Create(InitializeAsync());
}
专用异步任务InitializeAsync()
{
var ret=await i2adasservicehelper.GetTileViewItemsAsync();
此项=新的可观察集合(ret);
}
}
(假设您希望开始在构造函数中加载数据。)
然后,您可以直接绑定到项
,也可以绑定到初始化。对于快乐的情况,IsSuccessfullyCompleted
;对于悲伤的情况,IsFaulted
和Initialization.ErrorMessage
等等。什么是pr1
?这不应该是pr1.IsVisible=true代码>?我相信App.ViewModel.LoadData()应该是App.ViewModel.LoadDataAsync()(多次)
public async Task LoadDataAsync()
{
await FetchTileViewItemsAsync();
}
private async Task FetchTileViewItemsAsync()
{
var ret = await I2ADataServiceHelper.GetTileViewItemsAsync();
this.Items = new ObservableCollection<TileViewItem>(ret);
this.IsDataLoaded = true;
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
await App.ViewModel.LoadDataAsync();
}
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
try
{
if (!App.ViewModel.IsDataLoaded)
{
await App.ViewModel.LoadDataAsync();
}
}
catch (Exception ex)
{
...
}
}
public sealed class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<TileViewItem> Items
{
get { return _items; }
private set { _items = value; RaisePropertyChanged(); }
}
public ITaskCompletionNotifier Initialization { get; private set; }
public MyViewModel()
{
Initialization = TaskCompletionNotifierFactory.Create(InitializeAsync());
}
private async Task InitializeAsync()
{
var ret = await I2ADataServiceHelper.GetTileViewItemsAsync();
this.Items = new ObservableCollection<TileViewItem>(ret);
}
}