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

为何按下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。请问哪里操作有误?


问题原因与解决方法

核心原因

  1. 重新绑定数据源触发重复事件:调用LoadCompanyNameAliases()时,DataGridView重新绑定数据源,会再次触发CellValueChanged事件,形成循环。
  2. 取消删除未恢复原始值:用户选择No取消删除时,仅执行return,但单元格的空白值未恢复,导致每次重新绑定后,事件因空白值再次触发。

修复方案

  1. 加载数据前临时解绑事件:避免重新绑定数据源时触发CellValueChanged。
  2. 取消删除时恢复原始值:还原单元格和数据对象的原始内容,消除触发事件的诱因。
  3. 优化单元格值获取逻辑:直接通过事件参数的行列索引获取单元格,避免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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 04:25:28