自定义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; } } } }
问题原因
- 构造函数初始化顺序错误:自定义控件构造函数中,
InitializeComponent()(控件基础初始化逻辑)晚于事件绑定,可能导致初始化过程中触发异常事件。 - OnEnter逻辑无状态判断:每次触发
OnEnter都会强制设置CurrentCell并调用BeginEdit(true),开启编辑后焦点转移到编辑控件,结合Form_Load提前调用Focus()的时序问题,会导致DataGridView再次获得焦点,触发第二次OnEnter。 - 编辑控件事件重复绑定:
EditingControlShowing事件每次触发都会绑定新的事件处理器,未清理旧绑定,可能加剧事件循环问题。
解决方法
- 调整构造函数初始化顺序
将InitializeComponent()放在构造函数首位,确保控件完成基础初始化后再绑定事件:
public CustomControl1() { InitializeComponent(); this.KeyDown += new KeyEventHandler(CustomDataGridView_KeyDown); }
- 在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); } }
- 延迟设置焦点到Form_Shown事件
将焦点设置逻辑从Form_Load移到Form_Shown,确保控件完全加载后再操作:
private void Form2_Shown(object sender, EventArgs e) { customControl11.Focus(); }
- 清理编辑控件的旧事件绑定
在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
相关产品推荐
相关产品推荐

