Xamarin.Forms使用CommunityToolkit.Mvvm绑定ContentView数据不显示问题
核心问题是你在MainPage中获取的RecommendationViewModel实例和RecommendationsView绑定的实例不是同一个。由于你在DI容器中将RecommendationViewModel注册为AddTransient,每次调用GetRequiredService都会创建全新的对象——你在OnAppearing里初始化数据的是一个独立实例,而ListView绑定的是另一个空实例,因此数据无法显示。
1. 修改MainViewModel,持有共享的RecommendationViewModel实例
利用CommunityToolkit.Mvvm的ObservableProperty特性,让MainViewModel包含RecommendationViewModel的实例,并通过构造注入获取:
public partial class MainViewModel : ObservableObject { [ObservableProperty] private RecommendationViewModel _recommendationViewModel; public MainViewModel(RecommendationViewModel recommendationViewModel) { RecommendationViewModel = recommendationViewModel; } }
2. 调整MainPage的XAML,传递绑定上下文
让RecommendationsView的BindingContext绑定到MainViewModel的RecommendationViewModel属性,确保视图使用和MainPage操作的是同一个实例:
<ContentPage.Content> <controls:RecommendationsView BindingContext="{Binding RecommendationViewModel}" /> </ContentPage.Content>
3. 修改MainPage的OnAppearing方法
直接调用MainViewModel中持有的RecommendationViewModel实例的初始化方法:
protected override async void OnAppearing() { await ViewModel.RecommendationViewModel.InitializeAsync(); base.OnAppearing(); }
4. 优化RecommendationViewModel(可选但推荐)
使用CommunityToolkit.Mvvm的ObservableProperty自动处理属性变更通知,替代手动调用OnPropertyChanged:
public partial class RecommendationViewModel : ObservableObject { [ObservableProperty] private ObservableCollection<Recommendation> _recommendations; public RecommendationViewModel() { Recommendations = new ObservableCollection<Recommendation>(); } public async Task InitializeAsync() { var recommendations = DummyData.CreateDummyRecommendations(); Recommendations = new ObservableCollection<Recommendation>(recommendations); } }
5. 移除RecommendationsView中重复的BindingContext设置
删掉Recommendations.xaml中硬编码的BindingContext:
<!-- 移除这一段 --> <ContentView.BindingContext> <vm:RecommendationViewModel /> </ContentView.BindingContext>
同时删掉Recommendations.xaml.cs构造函数中的BindingContext赋值:
public RecommendationsView() { InitializeComponent(); // 移除这一行:BindingContext = Ioc.Default.GetRequiredService<RecommendationViewModel>(); }
6. 可选:调整DI注册模式
如果业务场景允许,也可以将RecommendationViewModel的注册从AddTransient改为AddSingleton或AddScoped,确保同一作用域内获取的是同一个实例。但更推荐上面的父子ViewModel持有实例的方式,因为它更符合MVVM的组件关系设计。
内容的提问来源于stack exchange,提问作者user3569465

