.NET MAUI中ObservableCollection项属性变更后CollectionView不更新
解决.NET MAUI CollectionView属性变更不即时更新UI的问题
核心问题分析
你的代码存在三个关键问题导致UI无法即时更新:
ShopingCart模型未实现属性变更通知:你仅在ViewModel中使用[ObservableProperty],但ShopingCart类本身未实现INotifyPropertyChanged,修改它的Qty和Total属性时不会触发UI更新。ButtonView未正确绑定命令与参数:自定义ButtonView未将点击事件关联到ViewModel的IncreaseProduct命令,也未传递当前的ShopingCart对象。- ViewModel存在冗余属性:ViewModel中
productName、qty、total等属性属于ShopingCart模型,放在ViewModel中完全多余,会混淆绑定逻辑。
分步解决方案
1. 修复ShopingCart模型的属性变更通知
让ShopingCart继承ObservableObject并添加[ObservableProperty]特性,确保属性变更时触发通知:
using CommunityToolkit.Mvvm.ComponentModel; public partial class ShopingCart : ObservableObject { [ObservableProperty] private int idShopingCar; [ObservableProperty] private string productName; // 修正原错误:类型应为string而非int [ObservableProperty] private int qty; [ObservableProperty] private int total; [ObservableProperty] private int idProduct; [ObservableProperty] private int unitPrice; }
2. 清理ViewModel的冗余属性
删除ViewModel中属于ShopingCart模型的冗余属性,只保留视图所需的集合和总计属性:
public partial class ShoppingListViewModel : BaseViewModel { public ShoppingListViewModel() { ShopingCartsList = new ObservableCollection<ShopingCart>(); _ = GetProducts(); } [ObservableProperty] private ObservableCollection<ShopingCart> shopingCartsList; [ObservableProperty] private int totalProducts; [ObservableProperty] private double totalSum; // 移除以下冗余属性:idShopingCar、productName、qty、total、idProduct、unitPrice public async Task GetProducts() { var objList = await App.ShopingCartRepo.GetItemsAsync(); ShopingCartsList = new ObservableCollection<ShopingCart>(objList); UpdateTotals(); } private void UpdateTotals() { TotalSum = ShopingCartsList.Sum(x => x.Total); TotalProducts = ShopingCartsList.Count; } [RelayCommand] public async Task IncreaseProduct(ShopingCart selectedProduct) { if (selectedProduct == null) return; // 直接使用传入的对象,无需重复查找 selectedProduct.Qty += 1; selectedProduct.Total = selectedProduct.Qty * selectedProduct.UnitPrice; Console.WriteLine($"Product updated: Qty={selectedProduct.Qty}, Total={selectedProduct.Total}"); UpdateTotals(); await App.ShopingCartRepo.SaveItemAsync(selectedProduct); await App.Current.MainPage.DisplayAlert("Note", "Product Updated", "Ok"); } }
3. 修正ButtonView的命令绑定
修改ButtonView的XAML,将命令绑定到ViewModel的IncreaseProduct命令,并传递当前ShopingCart对象:
<!-- ButtonView.xaml --> <ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:viewmodels="clr-namespace:YourAppNamespace.ViewModels" x:Class="YourAppNamespace.views.ButtonView"> <HorizontalStackLayout> <Button Text="+" Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodels:ShoppingListViewModel}}, Path=IncreaseProductCommand}" CommandParameter="{Binding .}"/> <!-- 可添加减号按钮,绑定对应的DecreaseProduct命令 --> </HorizontalStackLayout> </ContentView>
注意:替换
YourAppNamespace为你实际的项目命名空间。
4. 可选:确认CollectionView绑定模式
虽然ObservableCollection默认支持集合变更通知,若仍有问题可显式指定双向绑定:
<CollectionView ItemsSource="{Binding ShopingCartsList, Mode=TwoWay}" Grid.Row="1" Margin="0,40,0,0"> <!-- 原有ItemTemplate代码不变 --> </CollectionView>
验证效果
修改完成后,点击ButtonView的加号按钮:
- CollectionView中对应商品的
Qty和Total会即时更新 - 顶部的
TotalProducts和TotalSum标签同步更新 - 无需离开页面即可看到变更
内容的提问来源于stack exchange,提问作者Luis Julio
相关产品推荐
相关产品推荐

