C# Xamarin.Forms中如何将ViewModel层异步等待数据传递到View层
问题根因
locations是公共字段,XAML数据绑定仅支持绑定公共属性,不支持字段- 未实现属性变更通知,异步赋值完成后UI无法收到变更通知
- 绑定数据源类型不匹配:
LocationsList是包装类,实际可渲染的列表数据是其内部的Locations属性,直接绑定包装类无法正常渲染列表
修改方案
1. 调整LocationsViewModel属性定义
你继承的BaseViewModel默认已封装INotifyPropertyChanged相关逻辑,直接使用其提供的属性变更通知方法即可:
class LocationsViewModel : BaseViewModel { private Location deviceLocation; // 替换原有public LocationsList locations;字段 private LocationsList _locations; public LocationsList Locations { get => _locations; set { _locations = value; OnPropertyChanged(); // 方法名与BaseViewModel保持一致,部分模板可能叫NotifyPropertyChanged // 同步通知列表属性变更 OnPropertyChanged(nameof(LocationItems)); } } // 暴露给ListView绑定的实际列表属性 public List<LocationItem> LocationItems => Locations?.Locations; // 若后续需要动态增删列表项,将List替换为ObservableCollection<LocationItem>即可 public LocationsViewModel() { Title = "Lokacije"; // 建议将此处调用移到Page的OnAppearing中,避免构造函数异步逻辑吞异常 // RunAsyncMethods(); } // 改返回值为Task,避免async void丢异常 public async Task RunAsyncMethods() { Locations = await FetchLocationsJson(); deviceLocation = await FetchDeviceLocation(); Locations = await SortLocationsByProximity(deviceLocation, Locations); } }
2. 修改XAML绑定路径
将ListView的ItemsSource绑定到新增的列表属性:
<ListView Grid.Row="1" x:Name="LocationsListView" ItemsSource="{Binding LocationItems}" ...>
3. 可选:优化异步逻辑触发时机
在LocationsPage.xaml.cs中添加页面生命周期触发逻辑,避免构造函数异步异常:
protected override async void OnAppearing() { base.OnAppearing(); if (BindingContext is LocationsViewModel vm && vm.Locations == null) { await vm.RunAsyncMethods(); } }
补充说明
如果后续修改LocationItem的属性(比如Proximity)需要同步更新UI,需要让LocationItem也继承BaseViewModel,给每个属性加上变更通知逻辑即可。
内容的提问来源于stack exchange,提问作者s3c
相关产品推荐
相关产品推荐

