在CommunityToolkit.Maui Popup中用CollectionView时抛出集合修改异常
解决CommunityToolkit.Maui Popup中CollectionView抛出"Collection was modified; enumeration operation may not execute"异常
问题场景
在CommunityToolkit.Maui的Popup组件中嵌入CollectionView展示可滚动列表,弹窗显示时立即抛出异常:Collection was modified; enumeration operation may not execute,但绑定的ItemsSource集合并未被手动增删修改。
可能原因
- 源列表枚举冲突:构造
ObservableCollection时传入的[other list]可能正在被其他线程修改,此时ObservableCollection内部枚举源列表初始化时,会触发集合修改与枚举的并发冲突。 - 绑定时机问题:集合赋值与UI组件初始化的顺序不当,导致CollectionView在枚举集合时,集合尚未完全初始化完成。
- ItemSizingStrategy触发的枚举冲突:当设置
ItemSizingStrategy="MeasureAllItems"时,CollectionView会一次性枚举所有项进行尺寸测量,若此时集合存在隐式修改(如绑定的元素属性变更间接触发集合状态变化),也会引发异常。
解决方案
1. 隔离源列表,避免并发修改
构造ObservableCollection时,先创建源列表的副本,确保初始化过程中不会受原列表的外部修改影响:
public PopupTest() { // 创建源列表的独立副本,避免原列表被外部修改干扰 var sourceListCopy = new List<YourItemType>(otherList); Sources = new ObservableCollection<YourItemType>(sourceListCopy); // 显式设置BindingContext,确保XAML绑定能正确找到Sources属性 BindingContext = this; InitializeComponent(); }
2. 调整初始化顺序
确保集合完全初始化后再进行UI组件初始化,同时显式设置BindingContext:
public PopupTest() { // 先完成集合初始化 Sources = new ObservableCollection<YourItemType>(new List<YourItemType>(otherList)); // 设置绑定上下文 BindingContext = this; // 最后初始化UI组件 InitializeComponent(); }
3. 检查双向绑定的影响
若RadioButton的IsChecked使用了双向绑定,确保绑定的属性变更不会间接触发集合的修改操作。可以暂时移除RadioButton的绑定,测试是否还会抛出异常,以此排查是否是属性变更导致的隐式集合冲突。
4. 使用线程安全的集合操作
如果源列表来自后台线程的异步操作,确保在UI线程中完成集合的初始化:
public PopupTest() { InitializeComponent(); BindingContext = this; // 若源列表来自异步操作,确保在UI线程更新集合 MainThread.BeginInvokeOnMainThread(() => { var sourceCopy = new List<YourItemType>(otherList); Sources = new ObservableCollection<YourItemType>(sourceCopy); }); }
验证修改
完成上述修改后,重新调用弹窗:
var popup = new PopupTest(); this.ShowPopup(popup);
内容的提问来源于stack exchange,提问作者Charstar
相关产品推荐
相关产品推荐

