WPF DataGrid绑定自引用对象触发DeferRefresh异常如何解决
报错原因
你遇到的报错:
System.InvalidOperationException: 'DeferRefresh' is not allowed during an AddNew or EditItem transaction.
核心是DataGrid处于编辑事务状态时,你绑定的ComboBox下拉数据源触发了集合变更通知,DataGrid内部试图调用DeferRefresh更新视图,但编辑事务状态下不允许执行该操作。你的Feeders DataGrid的FedFrom列ComboBox绑定的就是网格自身的数据源集合,点击下拉进入编辑模式时的绑定刷新逻辑和编辑事务产生了冲突,才会触发报错。
解决方案
按实施复杂度和效果优先级排列:
方案1:编辑前提交已有事务+调整绑定更新时机(改动最小,推荐)
- 给展示Feeders的DataGrid添加
BeginningEdit事件处理,进入编辑前先提交未完成的编辑事务:
private void FeederDataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e) { var dataGrid = sender as DataGrid; if (dataGrid.IsEditingItem) { // 提交当前行的所有编辑内容 dataGrid.CommitEdit(DataGridEditingUnit.Row, true); } }
- 调整生成ComboBox列时的绑定配置,指定更新时机为失焦时:
cb.SelectedValueBinding = new Binding("FedFrom") { UpdateSourceTrigger = UpdateSourceTrigger.LostFocus, Mode = BindingMode.TwoWay };
方案2:使用独立的集合视图避免实时刷新冲突
如果方案1不能解决,说明你的场景下Feeders集合变更频繁,需要把ComboBox的数据源和网格自身的数据源做隔离:
- 全局声明独立的集合视图作为ComboBox的数据源:
private ListCollectionView FeederComboBoxSource;
- 初始化Feeders集合时同步初始化集合视图,关闭实时刷新:
Feeders = new ObservableCollection<Feeder>(); FeederComboBoxSource = new ListCollectionView(Feeders); // 关闭实时排序/过滤刷新,避免集合变更自动触发视图更新 FeederComboBoxSource.IsLiveSorting = false; FeederComboBoxSource.IsLiveFiltering = false;
- 生成ComboBox列时绑定这个独立视图(你代码里的
DteqList替换为FeederComboBoxSource):
cb.ItemsSource = FeederComboBoxSource;
- 监听Feeders集合变更,仅在非编辑状态下刷新下拉视图:
Feeders.CollectionChanged += (s, e) => { if (!feederDataGrid.IsEditingItem && !feederDataGrid.IsAddingNew) { FeederComboBoxSource.Refresh(); } };
方案3:使用静态快照(适合下拉列表不需要实时更新的场景)
如果不需要新增Feeder后立刻同步到正在编辑的下拉列表,直接用集合快照作为数据源,彻底避免集合变更通知:
// 生成列时直接用快照,不会触发变更通知 cb.ItemsSource = Feeders.ToList();
如果需要手动更新下拉列表,在每次新增/删除Feeder后重新赋值所有ComboBox列的ItemsSource即可。
内容的提问来源于stack exchange,提问作者pdeault
相关产品推荐
相关产品推荐

