如何避免DataGridView删除行时CellContentClick事件重复触发?
解决DataGridView删除行时CellContentClick重复触发的问题
这个问题我之前也碰到过,确实挺烦人的——删除行后DataGridView因数据源更新刷新,新行的按钮刚好占据了原删除行的位置,导致CellContentClick事件被意外重复触发。给你几个实用的解决办法:
方法一:临时移除事件处理程序
在执行删除操作前后,先解绑再重新绑定事件处理程序,这样DataGridView刷新时就不会触发重复的点击事件。记得用try-finally确保事件始终能重新绑定,避免异常导致事件丢失:
private void dg_list_EliminarBlogClick(object sender, DataGridViewCellEventArgs e) { var senderGrid = (DataGridView)sender; if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >= 0 && e.ColumnIndex == dg_lista_blogs.Columns["Eliminar"].Index) { MessageBoxHelper.PrepToCenterMessageBoxOnForm(this); DialogResult dialogResult = MessageBox.Show("Are you sure?", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.Yes) { // 临时解绑事件 senderGrid.CellContentClick -= dg_list_EliminarBlogClick; try { mylist.RemoveAt(dg_lista_blogs.CurrentRow.Index); } finally { // 重新绑定事件 senderGrid.CellContentClick += dg_list_EliminarBlogClick; } } } }
方法二:使用“正在处理”标志位
定义一个类级别的布尔变量,用来标记当前是否正在执行删除操作。事件触发时先检查这个标志,若处于删除状态则直接跳过逻辑,避免重复执行:
首先在类中添加标志变量:
private bool _isDeleting = false;
然后修改事件处理方法:
private void dg_list_EliminarBlogClick(object sender, DataGridViewCellEventArgs e) { // 如果正在删除,直接返回 if (_isDeleting) return; var senderGrid = (DataGridView)sender; if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >= 0 && e.ColumnIndex == dg_lista_blogs.Columns["Eliminar"].Index) { MessageBoxHelper.PrepToCenterMessageBoxOnForm(this); DialogResult dialogResult = MessageBox.Show("Are you sure?", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.Yes) { _isDeleting = true; try { mylist.RemoveAt(dg_lista_blogs.CurrentRow.Index); } finally { // 无论是否出错,都恢复标志位 _isDeleting = false; } } } }
方法对比
- 标志位方法更简洁,代码侵入性低,适合大多数场景;
- 解绑事件方法适合更复杂的UI交互场景,但需要注意异常处理,防止事件绑定丢失。
内容的提问来源于stack exchange,提问作者Jose Antonio Mateos
相关产品推荐
相关产品推荐

