带有按钮、组合框和文本框的 C# WinForms (.NET Framework) DataGridView:使用按钮添加新行以添加组合框项时出错
Posted
技术标签:
【中文标题】带有按钮、组合框和文本框的 C# WinForms (.NET Framework) DataGridView:使用按钮添加新行以添加组合框项时出错【英文标题】:C# WinForms (.NET Framework) DataGridView with Button, Combo Box & Text Box: Errors adding New Row using Button to Add Combo Box Item 【发布时间】:2021-11-21 16:46:50 【问题描述】:我有一个 Windows 窗体应用程序 (.NET Framework) 来显示 SQL 数据库中的记录。表单显示单个记录并通过记录确定。每条记录可能没有或有更多相关记录(磁盘上与父记录相关的文件列表)(在 M:M 关系中),所以我使用 DataGridView 来显示相关记录。 DGV 有 4 列:一个按钮列,它打开一个表单,作为一个对话框,将新文件添加到数据库的文件列表中,第二个按钮列使用其常用命令行打开文件,一个组合框列绑定到所有文件的列表并显示文件名,以及显示文件类型的文本框列。
就显示而言,一切正常,包括在浏览所有父记录、创建新父记录、删除父记录或更新父记录时。所有也可以添加新行,删除行,甚至更新一行上的选定文件。当尝试使用 Add New 按钮(第一个 Button 列)添加一个不在列表中的新文件时,问题就开始了。如果我在现有行上执行此操作,则没有问题,新文件被添加并在下拉列中选择,新文件的文件类型显示在文本框列中。但是,我无法从新行中完成这项工作,换句话说,我无法使用添加新按钮在 DGV 的新空白行中添加新文件。
我遇到的第一个错误是因为新行的 DataBoundItem 为空。由于这是一个只读属性,我无法设置它。我尝试使用该过程以编程方式添加此处几篇文章中描述的新行,但出现错误,我无法以编程方式添加数据绑定的行。在这一点上,我真的不确定我错过了什么。
以下是代码的相关部分。在选择父记录(或创建新记录)时,调用 BindExperimentFilesDataGridView 方法:
private void BindExperimentFilesDataGridView(ExperimentModel currentExperiment)
// TODO -- set formatting properties for DataGridView
List<FileModel> filesbyexperiment = _sql.GetFilesByExperimentId(currentExperiment.Id);
_currentExperimentFileIds = new List<int>();
foreach ( FileModel f in filesbyexperiment )
_currentExperimentFileIds.Add(f.Id);
_experimentFiles = new BindingList<FileModel>(filesbyexperiment);
experimentFilesDataGridView.AutoGenerateColumns = false;
experimentFilesDataGridView.DataSource = _experimentFiles;
FileNameColumn.DataSource = _allFiles;
FileNameColumn.DataPropertyName = nameof(FileModel.FileName);
FileNameColumn.DisplayMember = nameof(FileModel.FileName);
FileNameColumn.ValueMember = nameof(FileModel.FileName);
FileTypeColumn.DataPropertyName = nameof(FileModel.FileTypeName);
单击添加新按钮是通过 CellClick 事件处理的:
private void ExperimentFilesDataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
// ignore clicks that are not on button cells
if ( e.RowIndex < 0 || e.ColumnIndex == addNewFileButtonColumn.Index )
NewFileDialogForm newfiledialogform = new NewFileDialogForm(this, e.RowIndex);
newfiledialogform.Show();
if ( e.RowIndex < 0 || e.ColumnIndex == openFileButtonColumn.Index )
DataGridViewRow row = experimentFilesDataGridView.Rows[e.RowIndex];
FileModel data = row.DataBoundItem as FileModel;
OpenFile(data);
当 NewFileDialogForm 返回时,它会调用父窗体的 SelectFiles 方法:
public void SelectFile(FileModel fileModel, int rowIndex)
DataGridViewRow row = experimentFilesDataGridView.Rows[rowIndex];
DataGridViewCell cell = row.Cells[FileNameColumn.Index];
cell.Value = fileModel.FileName;
FileNameColumn(也就是ComboBoxColumn)中cell.Value的改变触发了Cell Value Changed事件,它的handler负责设置Text Box列中文件类型的值: 私人无效 ExperimentFilesDataGridView_CellValueChanged(对象发送者,DataGridViewCellEventArgs e) if ( e.RowIndex
DataGridViewRow row = experimentFilesDataGridView.Rows[e.RowIndex];
DataGridViewCell cell = row.Cells[e.ColumnIndex];
if ( cell is DataGridViewComboBoxCell )
string newfilename = (string)cell.Value;
FileModel newdatafilelink = _allFiles.Where(x => x.FileName == newfilename).FirstOrDefault();
FileModel editedfilename = row.DataBoundItem as FileModel;
editedfilename.Id = newdatafilelink.Id;
editedfilename.FileName = newdatafilelink.FileName;
editedfilename.FileTypeId = newdatafilelink.FileTypeId;
editedfilename.FileType = newdatafilelink.FileType;
editedfilename.CreatedDate = newdatafilelink.CreatedDate;
editedfilename.LastUpdate = newdatafilelink.LastUpdate;
row.Cells["FileTypeColumn"].Value = newdatafilelink.FileTypeName;
experimentFilesDataGridView.InvalidateRow(e.RowIndex);
if ( newdatafilelink.Id < 1 )
DialogResult result = MessageBox.Show("Do you want to delete the row?", "Confirm Delete of Blank Row", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if ( result == DialogResult.Yes )
experimentFilesDataGridView.Rows.RemoveAt(e.RowIndex);
正如我所说,除了从新行点击“添加新”按钮的第一种情况外,一切正常。从现有行中点击 Add New 按钮可以正常工作。使用组合框列中的下拉菜单在现有行和新行中都可以正常工作。任何想法我缺少什么或如何使它工作?
请保持温和,因为这是我在 *** 上的第一个问题。
提前致谢, 皮埃尔
【问题讨论】:
对不起,如果我遗漏了什么。但是……我不得不问……你为什么要在网格的每一行上添加一个Add New
按钮?如果每一行上的 Add-New
按钮都做同样的事情,那么一 (1) 个外部按钮不是更有意义吗?我只是说“行”上的按钮意味着该按钮仅适用于该行,除非我遗漏了什么,否则这里似乎并非如此。
另外,如果问题是在添加新的数据行时......那么这段代码在哪里?我猜这个代码可能在NewFileDialogForm
中,没有显示。换句话说,实际上尝试将新数据添加到网格的代码似乎丢失了。这是故意的吗?
【参考方案1】:
首先,由于您的表是数据绑定的,不建议直接通过cell.Value="something";
修改其内容。最好修改数据源中的数据,例如_experimentFiles[i].FileName="something"
。如果您的数据源正确实施,此更改将立即反映在 UI 中。在某些情况下,直接修改也可能有效,但最好避免这种情况。
其次,对于新的行按钮处理程序。正如您已经发现的那样,这是一个极端情况,因为新行确实是空的并且没有数据源。因此,您应该按照以下方式单独处理这种情况
if(row.DataBoundItem as FileModel is null)
var fileName = //get filename as you want.
var newFileModel = new FileModelFileName = fileName;
_experimentFiles.Add(fileName)
else
//handle the normal case of existing row as you already doing.
您可以考虑通过检查data
中的null
并按照所述执行操作,将所有这些逻辑移到您的OpenFile
函数中。
【讨论】:
谢谢@Serg,解决了边缘情况。 不过,我也为我的礼仪违规行为道歉;我希望我在 之前在 YouTube 上看过 @IAmTimCorey 的 *** 礼仪视频我问了这个问题!!以上是关于带有按钮、组合框和文本框的 C# WinForms (.NET Framework) DataGridView:使用按钮添加新行以添加组合框项时出错的主要内容,如果未能解决你的问题,请参考以下文章