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

DevExpress Grid控件按Tab键时抛出空引用异常求助

解决Grid验证后失焦按Tab触发空引用异常的问题

我来帮你梳理下这个DevExpress GridView里的棘手问题:在RepositoryItemTextEdit完成验证并赋值对象后,行和单元格莫名失焦,此时按Tab键直接触发Object reference not set to an instance of an object异常,但手动重新选中单元格后操作又正常。结合你的代码和异常堆栈,我来分析下原因并给出解决方案。

问题根源分析

从错误堆栈能看到,异常出现在DevExpress.XtraGrid.Views.Grid.GridView.MoveNextCell()方法里——这说明当Tab键尝试切换单元格时,GridView找不到有效的焦点行/单元格,所以抛出了空引用。

你的验证逻辑里直接给TextEdit.EditValue赋值了复杂对象(Partitario),这个操作会触发GridView的行数据更新,间接打乱了控件的焦点状态;另外弹窗选择后的赋值操作是在委托里执行的,此时验证事件的上下文已经结束,控件焦点状态早已脱节。

解决方案

尝试以下几个步骤修复这个问题:

1. 赋值后强制恢复焦点

在给EditValue赋值完成后,手动让GridView重新聚焦到当前单元格,确保Tab键操作有明确的目标:

// 赋值完成后添加以下代码
gridView.FocusedRowHandle = gridView.FocusedRowHandle;
gridView.FocusedColumn = gridView.FocusedColumn;
gridView.ShowEditor(); // 重新激活单元格编辑器

2. 优化弹窗委托的执行逻辑

弹窗关闭后的赋值操作要放在UI线程上下文里执行,避免直接修改验证事件的e.Cancel状态(委托执行时验证上下文已结束):

form.FnOk += delegate (object item) {
    if (item is Partitario part) {
        this.Invoke(new Action(() => {
            gridView.SetFocusedRowCellValue(gridView.FocusedColumn, part);
            gridView.ShowEditor();
        }));
    }
};

3. 增加空值判断避免潜在异常

给sender转TextEdit、EditValue转字符串的操作都加上空值判断,提前拦截可能的空引用:

var textEdit = sender as TextEdit;
if (textEdit == null) return;

var codice = textEdit.EditValue?.ToString();
if(string.IsNullOrEmpty(codice)) {
    e.Cancel = true;
    return;
}

完整修改后的代码示例

private void OnRepositoryPartitariValidating(object sender, CancelEventArgs e) { 
    // 提前记录当前焦点状态
    var focusedRow = gridView.FocusedRowHandle;
    var focusedCol = gridView.FocusedColumn;
    
    var textEdit = sender as TextEdit;
    if (textEdit == null) return;
    
    var objConto = gridView.GetFocusedRowCellValue("Conto"); 
    if (textEdit.EditValue is Partitario) return; 
    
    var codice = textEdit.EditValue?.ToString();
    if(string.IsNullOrEmpty(codice)) {
        e.Cancel = true;
        return;
    }
    
    var partitario = Partitario.Manager.GetByCodice(codice); 
    if (partitario == null) { 
        e.Cancel = true; 
        var form = objConto is Conto 
            ? new ListPartitari((Conto)objConto) 
            : new ListPartitari();
            
        form.FnOk += delegate (object item) { 
            if (item is Partitario part) { 
                this.Invoke(new Action(() => {
                    gridView.SetFocusedRowCellValue(focusedCol, part);
                    gridView.FocusedRowHandle = focusedRow;
                    gridView.FocusedColumn = focusedCol;
                    gridView.ShowEditor();
                }));
            } 
        }; 
        form.ShowDialog(this); 
    } else { 
        textEdit.EditValue = partitario; 
        // 恢复焦点状态
        gridView.FocusedRowHandle = focusedRow;
        gridView.FocusedColumn = focusedCol;
        gridView.ShowEditor();
        //if (partitario.Conto.Id != ((Conto)objConto).Id) 
        // gridView.SetFocusedRowCellValue("Conto", partitario.Conto); 
    } 
}

额外提示

  • 尽量减少在验证事件中执行数据库查询这类耗时操作,必要时可以用异步加载避免UI卡顿;
  • 如果后续还要更新关联列(比如注释里的Conto列),建议放在GridView.CellValueChanged事件里执行,不要在验证事件中处理,进一步降低对焦点状态的干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:15:30