为何按下Enter时DataGridView.CellValueChanged会重复触发?
问题描述
我使用DataGridView展示数据,其中一列支持编辑——用户可双击编辑文本;按下<Enter>时会触发CellValueChanged事件。相关代码如下:
private void dgvCompanyNameAliases_CellValueChanged(object sender, DataGridViewCellEventArgs e) { var row = dgvCompanyNameAliases.Rows[e.RowIndex]; var companyNameMapping = (CompanyNameMapping)(row.Tag ?? row.DataBoundItem); companyNameMapping.Alias = dgvCompanyNameAliases.CurrentCell.EditedFormattedValue.ToString(); if (String.IsNullOrWhiteSpace(companyNameMapping.Alias)) { if (MessageBox.Show(String.Format(Resources.FrmSettings.ErrorQuestion_DeleteCompanyAliasConfirmMessage, companyNameMapping.Name), Resources.FrmSettings.ErrorQuestion_DeleteCompanyAliasConfirmTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { return; } _configSettings.Policies.ProjectNamingPolicies.CompanyNameMappings.DeleteAlias(companyNameMapping, _configSettings.Username); } else { companyNameMapping.Recorded = new Recorded { By = _configSettings.Username, On = DateTime.Now }; _configSettings.Policies.ProjectNamingPolicies.CompanyNameMappings.UpdateAlias(companyNameMapping); } LoadCompanyNameAliases(); } private void LoadCompanyNameAliases() { dgvCompanyNameAliases.DataSource = _configSettings.Policies.ProjectNamingPolicies.CompanyNameMappings.GetAllAliases() .OrderBy(companyNameMapping => companyNameMapping.Name) .ToList(); }
功能可用,但事件处理程序会重复触发,直到用户在确认对话框中选择No。请问哪里操作有误?
问题原因与解决方法
核心原因
- 重新绑定数据源触发重复事件:调用
LoadCompanyNameAliases()时,DataGridView重新绑定数据源,会再次触发CellValueChanged事件,形成循环。 - 取消删除未恢复原始值:用户选择
No取消删除时,仅执行return,但单元格的空白值未恢复,导致每次重新绑定后,事件因空白值再次触发。
修复方案
- 加载数据前临时解绑事件:避免重新绑定数据源时触发
CellValueChanged。 - 取消删除时恢复原始值:还原单元格和数据对象的原始内容,消除触发事件的诱因。
- 优化单元格值获取逻辑:直接通过事件参数的行列索引获取单元格,避免
CurrentCell可能带来的焦点错误。
修改后的代码
private void dgvCompanyNameAliases_CellValueChanged(object sender, DataGridViewCellEventArgs e) { // 过滤无效行/列 if (e.RowIndex < 0 || e.ColumnIndex < 0) return; var cell = dgvCompanyNameAliases[e.ColumnIndex, e.RowIndex]; var row = dgvCompanyNameAliases.Rows[e.RowIndex]; var companyNameMapping = (CompanyNameMapping)(row.Tag ?? row.DataBoundItem); // 保存原始值,用于取消操作时恢复 string originalAlias = companyNameMapping.Alias; string newAlias = cell.EditedFormattedValue.ToString().Trim(); companyNameMapping.Alias = newAlias; if (string.IsNullOrWhiteSpace(newAlias)) { if (MessageBox.Show(string.Format(Resources.FrmSettings.ErrorQuestion_DeleteCompanyAliasConfirmMessage, companyNameMapping.Name), Resources.FrmSettings.ErrorQuestion_DeleteCompanyAliasConfirmTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { // 恢复原始值 companyNameMapping.Alias = originalAlias; cell.Value = originalAlias; return; } _configSettings.Policies.ProjectNamingPolicies.CompanyNameMappings.DeleteAlias(companyNameMapping, _configSettings.Username); } else { companyNameMapping.Recorded = new Recorded { By = _configSettings.Username, On = DateTime.Now }; _configSettings.Policies.ProjectNamingPolicies.CompanyNameMappings.UpdateAlias(companyNameMapping); } // 临时解绑事件,避免加载数据时重复触发 dgvCompanyNameAliases.CellValueChanged -= dgvCompanyNameAliases_CellValueChanged; LoadCompanyNameAliases(); // 重新绑定事件 dgvCompanyNameAliases.CellValueChanged += dgvCompanyNameAliases_CellValueChanged; } private void LoadCompanyNameAliases() { dgvCompanyNameAliases.DataSource = _configSettings.Policies.ProjectNamingPolicies.CompanyNameMappings.GetAllAliases() .OrderBy(companyNameMapping => companyNameMapping.Name) .ToList(); }
内容的提问来源于stack exchange,提问作者awj
相关产品推荐
相关产品推荐

