You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xceed DataGrid库EndEdit报错:测试复现与解决方案咨询

Xceed DataGrid EndEdit() 错误:复现与解决方案

我之前在WPF项目里用Xceed DataGrid时也踩过这个坑,刚好能给你详细说说怎么复现这个错误,以及对应的解决办法。

如何复现这个错误

这个错误的核心原因是:你调用EndEdit()时,当前正在编辑的项已经不再属于DataGrid的数据源上下文了。以下是两种常见的复现场景:

场景1:编辑未提交的新行时移除该行

  1. 准备一个绑定了ObservableCollection<T>的Xceed DataGrid,实体类实现INotifyPropertyChanged
  2. 手动添加一条新行,点击某个单元格进入编辑状态(不要按回车或点击其他地方完成编辑)
  3. 通过代码把这条还在编辑中的新行从集合里移除
  4. 立即调用myGrid.EndEdit(),此时就会触发那个错误——因为被移除的行已经不在DataGrid的Items里了

你可以用Dispatcher模拟后台异步移除的场景,更贴近用户实际操作:

// 假设myCollection是绑定的ObservableCollection,myGrid是Xceed DataGrid
var newItem = new YourEntity();
myCollection.Add(newItem);
myGrid.SelectedItem = newItem;
myGrid.Focus();
// 模拟用户正在编辑,后台异步移除
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
    myCollection.Remove(newItem);
    myGrid.EndEdit(); // 这里会触发目标错误
}));

场景2:编辑现有行时切换数据源

  1. 编辑DataGrid中某一行的单元格,保持单元格处于激活编辑状态
  2. 把DataGrid的ItemsSource切换到另一个集合,或者直接清空原集合
  3. 调用myGrid.EndEdit(),同样会触发错误,因为原来的编辑项已经不在新的上下文里了

解决办法

针对这个问题,我们可以从提前处理编辑状态和调用EndEdit前校验上下文两个方向入手:

方案1:调用EndEdit前校验编辑项是否存在

在调用EndEdit()之前,先获取当前正在编辑的项,判断它是否还在DataGrid的Items集合里。如果不在,就取消编辑而不是强制结束:

var activeCell = myGrid.ActiveCell;
if (activeCell != null)
{
    var editingItem = activeCell.DataContext;
    if (myGrid.Items.Contains(editingItem))
    {
        // 项还在集合里,正常结束编辑
        myGrid.EndEdit();
    }
    else
    {
        // 项已经被移除,取消编辑
        myGrid.CancelEdit();
    }
}

方案2:修改数据源前先处理编辑状态

不管用户有没有完成编辑,在修改数据源(移除项、切换ItemsSource)之前,先提交或取消所有活跃的编辑会话,避免后续调用EndEdit时出错:

// 先提交单元格和行的编辑
myGrid.CommitEdit(DataGridEditingUnit.Cell, true);
myGrid.CommitEdit(DataGridEditingUnit.Row, true);

// 如果不需要提交编辑内容,也可以直接取消
// myGrid.CancelEdit(DataGridEditingUnit.Cell);
// myGrid.CancelEdit(DataGridEditingUnit.Row);

// 现在再修改数据源
myCollection.Remove(itemToRemove);
// 或者切换ItemsSource
// myGrid.ItemsSource = newCollection;

方案3:跟踪编辑状态,提前干预

通过监听DataGrid的编辑事件,维护当前正在编辑的项,在修改数据源时针对性处理:

private object _currentEditingItem;

private void MyGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
{
    _currentEditingItem = e.Row.DataContext;
}

private void MyGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    _currentEditingItem = null;
}

// 当需要移除元素时
if (_currentEditingItem != null && _currentEditingItem.Equals(itemToRemove))
{
    // 如果要移除的是正在编辑的项,先取消编辑
    myGrid.CancelEdit();
}
myCollection.Remove(itemToRemove);

方案4:使用Xceed专属API处理

Xceed DataGrid提供了一些更便捷的API来处理编辑状态,比如CommitAllEdits()可以一次性提交所有未完成的编辑:

// 先尝试提交所有编辑
var commitSuccess = myGrid.CommitAllEdits();
if (!commitSuccess)
{
    // 提交失败的话,取消所有编辑
    myGrid.CancelAllEdits();
}

// 再进行数据源操作
myCollection.Remove(itemToRemove);

另外,也可以通过myGrid.IsEditing属性判断当前是否处于编辑状态,再做对应处理。


内容的提问来源于stack exchange,提问作者Merta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:41:04