NET MAUI中MVVM命令修改double参数后视图未更新问题
购物车删除商品后总价不更新的修复方案
核心问题分析
你的代码中,删除商品后列表更新但总价不变化,主要有两个关键问题:
- ViewModel未实现
INotifyPropertyChanged接口:虽然你定义了PropertyChanged事件和通知方法,但未显式继承接口,导致绑定系统无法监听Sum属性的变化。 - 手动维护总价的方式易遗漏场景:构造函数累加、删除时扣除的逻辑,无法覆盖商品数量修改(比如Stepper调整)的情况,且容易因引用或计算错误导致总价不同步。
修复步骤与代码示例
1. 让ViewModel实现INotifyPropertyChanged接口
修改ViewModel类定义,明确继承接口:
class BusketViewModel : INotifyPropertyChanged
2. 将Sum改为动态计算的只读属性
放弃手动维护总价,改为实时从集合中计算,避免同步错误:
public double Sum { get { return ProductsInBasket?.Sum(item => item.product.Cost * item.quantityInBusket) ?? 0; } }
3. 监听集合与商品数量变化,触发总价更新
- 监听
ObservableCollection的CollectionChanged事件,在商品增删时通知Sum更新 - 监听每个商品的数量变化,在用户通过Stepper调整数量时同步更新总价
4. 修复异步加载的死锁问题
替换GetFromJsonAsync(...).Result为异步加载,避免UI线程阻塞:
完整修复后的ViewModel代码
class BusketViewModel : INotifyPropertyChanged { #region Fields private ObservableCollection<DTOProductAndQuantity> productsInBasket; private readonly HttpClient httpClient = new HttpClient(); private Command<object> deleteProductCommand; public event PropertyChangedEventHandler PropertyChanged; #endregion #region Constructor public BusketViewModel() { deleteProductCommand = new Command<object>(DeleteProduct); LoadBasketAsync(); } private async void LoadBasketAsync() { var productsFromHttp = await httpClient.GetFromJsonAsync<ObservableCollection<DTOProductAndQuantity>>("http://10.0.2.2:5125/api/Busket"); ProductsInBasket = new ObservableCollection<DTOProductAndQuantity>(productsFromHttp); // 监听集合增删事件,更新总价 ProductsInBasket.CollectionChanged += (s, e) => NotifyPropertyChanged(nameof(Sum)); // 监听每个商品的数量变化,更新总价 foreach (var item in ProductsInBasket) { if (item is INotifyPropertyChanged notifyItem) { notifyItem.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(DTOProductAndQuantity.quantityInBusket)) { NotifyPropertyChanged(nameof(Sum)); } }; } } } private void DeleteProduct(object obj) { if (obj is DTOProductAndQuantity productToDelete) { ProductsInBasket.Remove(productToDelete); // 无需手动修改Sum,CollectionChanged会自动触发更新 } } #endregion #region Properties public ObservableCollection<DTOProductAndQuantity> ProductsInBasket { get { return productsInBasket; } set { if (productsInBasket != value) { productsInBasket = value; NotifyPropertyChanged(); } } } public Command<object> DeleteProductCommand { get { return deleteProductCommand; } set { deleteProductCommand = value; } } public double Sum { get { return ProductsInBasket?.Sum(item => item.product.Cost * item.quantityInBusket) ?? 0; } } #endregion protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
5. 让DTOProductAndQuantity实现INotifyPropertyChanged
确保数量变化时能通知ViewModel更新总价:
public class DTOProductAndQuantity : INotifyPropertyChanged { private int quantityInBusket; public Product product { get; set; } public int quantityInBusket { get { return quantityInBusket; } set { if (quantityInBusket != value) { quantityInBusket = value; NotifyPropertyChanged(); } } } public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
修复说明
- 实现
INotifyPropertyChanged接口后,绑定系统能正确监听属性变化,UI会在Sum更新时自动刷新。 - 动态计算
Sum的方式,确保总价始终与购物车中的商品数量、价格保持一致,避免手动维护的错误。 - 监听集合和商品数量变化,覆盖了删除商品、调整数量等所有会影响总价的场景。
内容的提问来源于stack exchange,提问作者vhhs
相关产品推荐
相关产品推荐

