如何在集合增删元素时自动计算LeadPerformanceItem的visitorspercentoftotal属性?
当然有办法!这里有几种实用的方案,能帮你实现集合增删元素时自动计算visitorspercentoftotal属性的需求:
方案1:让Item持有所属集合的引用(最直接易懂)
核心思路是让每个LeadPerformanceItem知道自己属于哪个LeadPerformanceItemCollection,这样它就能随时获取最新的总访客数来计算百分比。
首先修改LeadPerformanceItem类,添加父集合的引用:
public class LeadPerformanceItem { // 持有所属集合的引用,用于获取总访客数 private LeadPerformanceItemCollection _parentCollection; public LeadPerformanceItemCollection ParentCollection { get => _parentCollection; set => _parentCollection = value; } public string name { get; set; } public int visitors { get; set; } public decimal visitorspercentoftotal { get { // 避免除以0的运行时错误 if (ParentCollection?.totalvisitors == 0) return 0; // 计算百分比,乘以100转为百分比格式 return (decimal)visitors / ParentCollection.totalvisitors * 100; } } }
然后改造LeadPerformanceItemCollection,确保增删元素时自动维护item的父集合引用:
public class LeadPerformanceItemCollection { private List<LeadPerformanceItem> _items = new List<LeadPerformanceItem>(); public List<LeadPerformanceItem> items { get => _items; set { // 先清空旧item的父引用 foreach (var item in _items) item.ParentCollection = null; _items = value; // 给新item绑定父集合 foreach (var item in _items) item.ParentCollection = this; } } public int totalvisitors { get { return items.Sum(x => x.visitors); } } // 推荐用自定义方法操作集合,代替直接调用List的Add/Remove public void AddItem(LeadPerformanceItem item) { if (item == null) return; item.ParentCollection = this; _items.Add(item); } public void RemoveItem(LeadPerformanceItem item) { if (_items.Remove(item)) { item.ParentCollection = null; } } }
这样,当你通过AddItem/RemoveItem操作集合时,每个item都会自动关联到父集合,visitorspercentoftotal每次被访问时,都会基于最新的总访客数计算出正确结果。
方案2:使用ObservableCollection(适合UI绑定场景)
如果你的项目是WPF/MAUI这类需要数据绑定自动刷新UI的场景,推荐用ObservableCollection<T>替代List<T>。它会在集合变化时触发CollectionChanged事件,结合INotifyPropertyChanged能让UI自动感知到百分比的更新。
示例代码如下:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; public class LeadPerformanceItem : INotifyPropertyChanged { private LeadPerformanceItemCollection _parentCollection; public LeadPerformanceItemCollection ParentCollection { get => _parentCollection; set { _parentCollection = value; // 通知UI百分比属性已变化 OnPropertyChanged(nameof(visitorspercentoftotal)); } } private string _name; public string name { get => _name; set { _name = value; OnPropertyChanged(); } } private int _visitors; public int visitors { get => _visitors; set { _visitors = value; OnPropertyChanged(); // 访客数变化时,百分比也会变,通知UI OnPropertyChanged(nameof(visitorspercentoftotal)); } } public decimal visitorspercentoftotal { get { if (ParentCollection?.totalvisitors == 0) return 0; return (decimal)visitors / ParentCollection.totalvisitors * 100; } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class LeadPerformanceItemCollection : INotifyPropertyChanged { private ObservableCollection<LeadPerformanceItem> _items; public ObservableCollection<LeadPerformanceItem> items { get => _items; set { if (_items != null) { _items.CollectionChanged -= Items_CollectionChanged; foreach (var item in _items) item.ParentCollection = null; } _items = value; if (_items != null) { _items.CollectionChanged += Items_CollectionChanged; foreach (var item in _items) item.ParentCollection = this; } OnPropertyChanged(nameof(totalvisitors)); } } public int totalvisitors { get { return items.Sum(x => x.visitors); } } public LeadPerformanceItemCollection() { _items = new ObservableCollection<LeadPerformanceItem>(); _items.CollectionChanged += Items_CollectionChanged; } private void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { // 绑定/解绑新增/移除的item的父集合 if (e.NewItems != null) { foreach (LeadPerformanceItem item in e.NewItems) item.ParentCollection = this; } if (e.OldItems != null) { foreach (LeadPerformanceItem item in e.OldItems) item.ParentCollection = null; } // 通知总访客数变化,同时触发所有item的百分比更新 OnPropertyChanged(nameof(totalvisitors)); foreach (var item in items) { item.OnPropertyChanged(nameof(item.visitorspercentoftotal)); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
这个方案不仅能自动计算百分比,还能让UI实时刷新最新数据,非常适合可视化场景。
关键注意点
- 永远要处理除以0的情况:当总访客数为0时,直接返回0,避免运行时异常。
- 如果一定要直接操作
List的Add/Remove方法,记得手动设置item的ParentCollection,否则百分比计算会失效。 - 非UI场景推荐方案1,代码更简洁;UI绑定场景优先方案2,减少手动维护的工作量。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

