You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI中ObservableCollection项属性变更后CollectionView不更新

解决.NET MAUI CollectionView属性变更不即时更新UI的问题

核心问题分析

你的代码存在三个关键问题导致UI无法即时更新:

  1. ShopingCart模型未实现属性变更通知:你仅在ViewModel中使用[ObservableProperty],但ShopingCart类本身未实现INotifyPropertyChanged,修改它的Qty和Total属性时不会触发UI更新。
  2. ButtonView未正确绑定命令与参数:自定义ButtonView未将点击事件关联到ViewModel的IncreaseProduct命令,也未传递当前的ShopingCart对象。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 07:18:13