C# WinForms(.NET Framework) DataGridView新行点击添加按钮新增下拉项报错问询
问题根因
你遇到的空白新增行操作失效核心原因有两个:
- DataGridView底部默认显示的空白行是占位行,仅用于提示用户输入,并没有对应绑定到
_experimentFiles中的FileModel实例,所以DataBoundItem属性为null,你在CellValueChanged中直接强制转换该属性为FileModel会触发空引用异常。 - 你原有的
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
相关产品推荐
相关产品推荐

