我有一個 Windows 表單應用程式 (.NET Framework) 來顯示來自 SQL 資料庫的記錄。該表單顯示單個記錄并通過記錄確定。每條記錄可能沒有或更多相關記錄(磁盤上與父記錄相關的檔案串列)(在 M:M 關系中),因此我使用 DataGridView 來顯示相關記錄。DGV 有 4 列:一個按鈕列,它打開一個表單,作為一個對話框,將一個新檔案添加到資料庫的檔案串列中,第二個按鈕列,使用其常用的命令列打開檔案,一個組合框列,系結到所有檔案的串列并顯示檔案名,以及顯示檔案型別的文本框列。
就顯示而言,一切都有效,包括在瀏覽所有父記錄、創建新父記錄、洗掉父記錄或更新父記錄時。添加新行,洗掉行,甚至更新行上的選定檔案都可以正常作業。當嘗試使用“添加新”按鈕(第一個“按鈕”列)添加不在串列中的新檔案時,問題就開始了。如果我在現有行上執行此操作,則沒有問題,新檔案將在下拉列中添加和選擇,新檔案的檔案型別將顯示在文本框列中。但是,我無法從新行開始這項作業,換句話說,我無法使用“添加新”按鈕在 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;
}
The change of cell.Value in the FileNameColumn (which is the ComboBoxColumn) triggers the Cell Value Changed event, and its handler is responsible for setting the value for the file type in the Text Box column: private void ExperimentFilesDataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) { if ( e.RowIndex < 0 || e.ColumnIndex < 0 ) { return; }
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);
}
}
}
}
As I said, everything works ok except in the 1 case of hitting the Add New button from a new row. Hitting the Add New button from an existing row works fine. Using the drop-down in the combo box column works fine in both existing rows and new rows. Any ideas what I'm missing or how to get this to work?
Please be gentle, as this is my first question on StackOverflow.
Thanks in advance, Pierre
uj5u.com熱心網友回復:
首先,由于您的表是資料系結的,因此不建議直接通過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 FileModel{FileName = fileName};
_experimentFiles.Add(fileName)
}
else
{
//handle the normal case of existing row as you already doing.
}
你可以考慮到這一切的邏輯進入你OpenFile的檢查功能data的null和所描述的進行操作。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/365948.html
標籤:c# winforms datagridview datagridcomboboxcolumn
上一篇:如何在回圈中顯示選中狀態?
