C# WPF中Dictionary与ObservableCollection对象实例共享及商品同步实现问题
解决方案
你不用考虑指针的问题,C#里的引用类型(你定义的Product和Customer都是class,属于引用类型)本身就是托管堆上的安全指针,所有购物车存的都是全局商品列表里的同一个实例,你现在已经实现的属性修改同步逻辑是完全正确的。
删除商品的同步需求用事件发布-订阅模式就能实现,完全不需要手动遍历所有客户,修改成本很低:
具体修改步骤
- 修复现有属性通知缺陷
你当前的Product类Modify方法修改属性后没有触发变更通知,WPF界面绑定时不会自动刷新,先修正这部分:
public class Product : INotifyPropertyChanged { // 把通知方法的访问修饰符改成protected,方便内部调用 protected void OnPropertyRaised(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } public void Modify(string _newname,double _price) { name = _newname; price = _price; // 新增属性变更通知 OnPropertyRaised(nameof(Name)); OnPropertyRaised(nameof(Price)); } // 其余原有代码保持不变 }
- 在
MarketServices中定义产品删除事件,封装删除操作
不要直接操作字典删除商品,封装统一的删除方法,删除时触发事件通知所有订阅方:
public class MarketServices { // 定义产品删除事件,参数为被删除的商品实例 public event Action<Product> ProductRemoved; // 封装商品删除方法 public bool RemoveProduct(string productKey) { if (ProductObjectsMainList_Services.Remove(productKey, out var removedProduct)) { // 触发删除事件 ProductRemoved?.Invoke(removedProduct); return true; } return false; } // 其余原有代码保持不变 }
- 客户类订阅删除事件,自动处理自身购物车数据
修改Customer构造函数,订阅全局商品删除事件,收到通知后自动移除对应商品:
public class Customer : INotifyPropertyChanged { // 构造函数新增MarketServices参数,用于订阅事件 public Customer(string _name, MarketServices market) { name = _name; Items = new ObservableCollection<Product>(); // 订阅商品删除事件 market.ProductRemoved += OnProductRemoved; } // 商品删除事件处理逻辑 private void OnProductRemoved(Product removedProduct) { if (Items.Contains(removedProduct)) { Items.Remove(removedProduct); } } // 其余原有代码保持不变 }
- 调整客户初始化逻辑,传入MarketServices实例
修改CreateCustomers方法中客户实例化的代码:
public void CreateCustomers() { CustomerObjectsMainList_Services.Add("CustomerA", new Customer("CustomerA", this)); CustomerObjectsMainList_Services.Add("CustomerB", new Customer("CustomerB", this)); // 其余原有代码保持不变 }
效果验证
你之前的测试代码中test.ProductObjectsMainList_Services["Peaches"] = null;只是把字典对应值设为null,并不是删除键值对,改用封装的RemoveProduct方法即可触发自动同步:
// 删除全局商品列表中的Apple test.RemoveProduct("Apple"); // 此时CustomerA和CustomerB购物车中的Apple会被自动移除,无需额外操作
拓展适配
如果需要实现商品标记为不可购买的功能,只需要给Product新增IsAvailable布尔属性,变更时触发PropertyChanged通知,在WPF界面绑定该属性做样式禁用、灰度展示即可,不需要额外的同步逻辑。
内容的提问来源于stack exchange,提问作者user15798960
相关产品推荐
相关产品推荐

