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

C# WinForms(.NET Framework) DataGridView新行点击添加按钮新增下拉项报错问询

问题根因

你遇到的空白新增行操作失效核心原因有两个:

  1. DataGridView底部默认显示的空白行是占位行,仅用于提示用户输入,并没有对应绑定到_experimentFiles中的FileModel实例,所以DataBoundItem属性为null,你在CellValueChanged中直接强制转换该属性为FileModel会触发空引用异常。
  2. 你原有的CellClick事件判断逻辑存在错误,e.RowIndex < 0代表点击了列头,你用了||逻辑会导致点击列头也触发按钮事件,甚至触发索引越界报错。

解决方案

1. 修改SelectFile方法,对占位新行单独处理

绑定模式下不要直接操作空白行的单元格,先往绑定源BindingList中新增FileModel实例,DGV会自动将占位行转为正式绑定行,再赋值即可:

public void SelectFile(FileModel fileModel, int rowIndex)
{
    var targetRow = experimentFilesDataGridView.Rows[rowIndex];
    // 判断当前行是否为占位新行
    if (targetRow.IsNewRow)
    {
        // 往绑定源新增实体,自动触发DGV行同步
        var newFile = new FileModel
        {
            FileName = fileModel.FileName,
            Id = fileModel.Id,
            FileTypeId = fileModel.FileTypeId,
            FileTypeName = fileModel.FileTypeName
        };
        _experimentFiles.Add(newFile);
        return;
    }
    // 已有行逻辑保持不变
    targetRow.Cells[FileNameColumn.Index].Value = fileModel.FileName;
}

2. 修正CellClick事件的判断逻辑

修复列头点击触发事件、新行点击打开按钮报错的问题:

private void ExperimentFilesDataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
    // 点击列头直接返回,避免索引越界
    if (e.RowIndex < 0) return;
    
    if (e.ColumnIndex == addNewFileButtonColumn.Index)
    {
        NewFileDialogForm newfiledialogform = new NewFileDialogForm(this, e.RowIndex);
        newfiledialogform.Show();
    }
    else if (e.ColumnIndex == openFileButtonColumn.Index)
    {
        var row = experimentFilesDataGridView.Rows[e.RowIndex];
        // 加空判断避免未绑定行点击报错
        if (row.DataBoundItem is FileModel data)
        {
            OpenFile(data);
        }
    }
}

3. 优化CellValueChanged事件的空判断与操作逻辑

绑定模式下优先操作绑定源实体,避免直接操作DGV单元格导致同步异常:

private void ExperimentFilesDataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (e.RowIndex < 0 || e.ColumnIndex < 0) return;
    
    var row = experimentFilesDataGridView.Rows[e.RowIndex];
    // 未绑定实体的行直接跳过
    if (row.DataBoundItem is not FileModel editedFile) return;
    if (row.Cells[e.ColumnIndex] is not DataGridViewComboBoxCell comboCell) return;

    var newFileName = comboCell.Value?.ToString();
    var targetFile = _allFiles.FirstOrDefault(x => x.FileName == newFileName);
    if (targetFile == null) return;

    // 直接修改绑定实体属性,DGV会自动同步显示
    editedFile.Id = targetFile.Id;
    editedFile.FileName = targetFile.FileName;
    editedFile.FileTypeId = targetFile.FileTypeId;
    editedFile.FileType = targetFile.FileType;
    editedFile.CreatedDate = targetFile.CreatedDate;
    editedFile.LastUpdate = targetFile.LastUpdate;

    experimentFilesDataGridView.InvalidateRow(e.RowIndex);

    if (targetFile.Id < 1)
    {
        var result = MessageBox.Show("Do you want to delete the row?", "Confirm Delete of Blank Row", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
        if (result == DialogResult.Yes)
        {
            // 绑定模式下删除绑定源实体即可,不需要直接操作DGV行
            _experimentFiles.Remove(editedFile);
        }
    }
}

补充注意事项

如果FileModel的属性变更后DGV没有自动刷新,需要让FileModel实现INotifyPropertyChanged接口,属性变更时触发PropertyChanged事件即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 22:24:05