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

DataGridView只读单元格更新时触发NullReferenceException问题求助

DataGridView更新只读列时出现NullReferenceException排查

问题场景

DataGridView中部分列设置为只读,但需要通过代码更新这些单元格的值;该控件的数据源是合并三个不同表的DataTable。当收到电报消息触发更新操作时,偶尔会出现NullReferenceException错误,不确定是否因更新只读单元格导致,附上相关代码求排查。

原代码

private void UpdateTrialSeqValue(string strProduct, string strBuy, string strSell,  string strBuy1Qty, string strSell1Qty)
{
    if (!this.IsDisposed && dgvWSettingAll != null)
    {
        if (this.InvokeRequired)
        {
            BeginInvoke(new MethodInvoker(() => UpdateTrialSeqValue(strProduct, strBuy, strSell, strBuy1Qty, strSell1Qty)));
            return;
        }

        lock (Update_Flag)
        {
            foreach (DataGridViewRow row in dgvSettingAll.Rows)
            {
                if(row.Index >= 0)
                {
                    string product = Convert.ToString(row.Cells["Colproduct"].Value);
                    if (product == strProduct)
                    {
                        row.Cells["ColBuyQty"].Value = strBuy1Qty;
                        row.Cells["ColBuyPrice"].Value = strBuy;
                        row.Cells["ColSellPrice"].Value = strSell;
                        row.Cells["ColSellQty"].Value = strSell1Qty;
                    }
                }
            }
        }
    }
}

可能的原因及解决方案

1. 单元格/行对象为空引发空引用

遍历dgvSettingAll.Rows时,可能存在未初始化的空行(比如控件自动生成的新行),导致row.Cells["Colproduct"]或目标单元格对象为null,访问其Value属性时触发异常。

解决方法:

  • 跳过新行:增加if (row.IsNewRow) continue;判断
  • 访问单元格前先检查对象是否为null

2. 只读列的更新限制混淆

DataGridView列设置ReadOnly=true仅禁止用户手动编辑,代码层面直接赋值是允许的;但如果绑定的DataTable对应列也设置了ReadOnly=true,则会导致赋值失败甚至报错。

解决方法:

  • 检查绑定的DataTable中目标列的ReadOnly属性,确保代码可修改
  • 优先更新数据源DataTable而非直接操作DataGridView单元格(绑定模式下更规范,避免控件与数据源状态不一致)

3. 多线程锁对象无效

lock (Update_Flag)的锁对象如果不是静态全局唯一的,会导致并发更新时无法互斥,引发对象状态异常。

解决方法:

  • 将Update_Flag定义为静态私有对象:private static readonly object Update_Flag = new object();

4. 参数或值为空的处理缺失

传入的参数或赋值内容为null时,虽然Convert.ToString能处理null,但直接赋值给单元格可能引发数据源兼容性问题(比如DataTable列不允许null)。

解决方法:

  • 赋值时将null转换为DBNull.Value,适配数据源要求

优化后的代码示例

// 确保锁对象静态唯一,避免并发冲突
private static readonly object Update_Flag = new object();

private void UpdateTrialSeqValue(string strProduct, string strBuy, string strSell, string strBuy1Qty, string strSell1Qty)
{
    if (this.IsDisposed || dgvSettingAll == null)
        return;

    if (this.InvokeRequired)
    {
        BeginInvoke(new MethodInvoker(() => UpdateTrialSeqValue(strProduct, strBuy, strSell, strBuy1Qty, strSell1Qty)));
        return;
    }

    lock (Update_Flag)
    {
        foreach (DataGridViewRow row in dgvSettingAll.Rows)
        {
            // 跳过未初始化的新行
            if (row.IsNewRow)
                continue;

            // 检查目标单元格是否存在
            var productCell = row.Cells["Colproduct"];
            if (productCell == null)
                continue;

            string product = Convert.ToString(productCell.Value);
            // 用不区分大小写的匹配避免字符串大小写问题
            if (string.Equals(product, strProduct, StringComparison.OrdinalIgnoreCase))
            {
                // 封装单元格更新逻辑,增加空判断和只读处理
                UpdateCellValue(row, "ColBuyQty", strBuy1Qty);
                UpdateCellValue(row, "ColBuyPrice", strBuy);
                UpdateCellValue(row, "ColSellPrice", strSell);
                UpdateCellValue(row, "ColSellQty", strSell1Qty);
                
                // 更推荐的方式:直接更新绑定的DataTable
                // if (row.DataBoundItem is DataRowView rowView)
                // {
                //     rowView.Row["ColBuyQty"] = strBuy1Qty ?? DBNull.Value;
                //     rowView.Row["ColBuyPrice"] = strBuy ?? DBNull.Value;
                //     // ...其他列赋值
                // }
                
                // 找到匹配行后退出循环,提升效率
                break;
            }
        }
    }
}

// 封装单元格更新方法,兼容只读列和空值
private void UpdateCellValue(DataGridViewRow row, string columnName, object value)
{
    var cell = row.Cells[columnName];
    if (cell == null)
        return;

    // 临时取消只读(如果需要),赋值后恢复
    bool wasReadOnly = cell.ReadOnly;
    if (wasReadOnly)
        cell.ReadOnly = false;
    
    // 处理空值,适配数据源要求
    cell.Value = value ?? DBNull.Value;
    
    if (wasReadOnly)
        cell.ReadOnly = true;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 19:33:22