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

自定义DataGridView的OnEnter事件被重复调用问题排查与解决

自定义DataGridView的OnEnter方法重复触发问题分析与解决

开发了一个继承自DataGridView的自定义控件CustomControl1,调试时发现其OnEnter方法被执行两次,执行流程为:OnEnter方法 → EditingControlShowing事件 → 再次触发OnEnter方法。相关代码如下:

自定义控件代码

public partial class CustomControl1 : DataGridView
{
    public CustomControl1()
    {
        this.KeyDown += new KeyEventHandler(CustomDataGridView_KeyDown);
       
        InitializeComponent();
    }
  protected override void OnEnter(EventArgs e)
    {
        base.OnEnter(e);
        this.CurrentCell = this.Rows[0].Cells[0];
        this.BeginEdit(true);
    }
}

使用控件的Form代码

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();         
    }

    private void Form2_Load(object sender, EventArgs e)
    {
      customControl11.Focus();
 }
    private void customControl11_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {            
        if (customControl11.CurrentCell.ColumnIndex == 0) 
        {
           TextBox textBox = e.Control as TextBox;
            if (textBox != null)
            {
                textBox.TextChanged += TextBox_TextChanged; 
                textBox.KeyDown += TextBox_KeyDown; 
                textBox.Enter += TextBox_Enter;                 

            }
        }
    }
}

问题原因

  1. 构造函数初始化顺序错误:自定义控件构造函数中,InitializeComponent()(控件基础初始化逻辑)晚于事件绑定,可能导致初始化过程中触发异常事件。
  2. OnEnter逻辑无状态判断:每次触发OnEnter都会强制设置CurrentCell并调用BeginEdit(true),开启编辑后焦点转移到编辑控件,结合Form_Load提前调用Focus()的时序问题,会导致DataGridView再次获得焦点,触发第二次OnEnter。
  3. 编辑控件事件重复绑定:EditingControlShowing事件每次触发都会绑定新的事件处理器,未清理旧绑定,可能加剧事件循环问题。

解决方法

  1. 调整构造函数初始化顺序
    将InitializeComponent()放在构造函数首位,确保控件完成基础初始化后再绑定事件:
public CustomControl1()
{
    InitializeComponent();
    this.KeyDown += new KeyEventHandler(CustomDataGridView_KeyDown);
}
  1. 在OnEnter中添加状态判断
    避免重复执行编辑逻辑,仅在未处于编辑模式且目标单元格未选中时操作:
protected override void OnEnter(EventArgs e)
{
    base.OnEnter(e);
    if (!this.IsCurrentCellInEditMode && this.CurrentCell != this.Rows[0].Cells[0])
    {
        this.CurrentCell = this.Rows[0].Cells[0];
        this.BeginEdit(true);
    }
}
  1. 延迟设置焦点到Form_Shown事件
    将焦点设置逻辑从Form_Load移到Form_Shown,确保控件完全加载后再操作:
private void Form2_Shown(object sender, EventArgs e)
{
    customControl11.Focus();
}
  1. 清理编辑控件的旧事件绑定
    在EditingControlShowing中绑定新事件前先移除旧绑定,防止重复触发:
private void customControl11_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{            
    if (customControl11.CurrentCell.ColumnIndex == 0) 
    {
       TextBox textBox = e.Control as TextBox;
        if (textBox != null)
        {
            textBox.TextChanged -= TextBox_TextChanged;
            textBox.KeyDown -= TextBox_KeyDown;
            textBox.Enter -= TextBox_Enter;

            textBox.TextChanged += TextBox_TextChanged; 
            textBox.KeyDown += TextBox_KeyDown; 
            textBox.Enter += TextBox_Enter;                 
        }
    }
}

内容的提问来源于stack exchange,提问作者ankit goel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 00:32:45