news 2026/6/11 14:30:02

datagridview控件如果是选中了新行,一旦其他控件获得焦点就自动选了最后一行

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
datagridview控件如果是选中了新行,一旦其他控件获得焦点就自动选了最后一行

如果是选中了新行,一旦其他控件获得焦点,比如BUTTON1 2026/6/11 0:30:03--e.RowIndex=9,IsNewRow=True 2026/6/11 0:30:04--e.RowIndex=8,IsNewRow=False 系统会自动选中最后一行,(只是触发了事件)但表面上没看出来

已完成思考

这是 DataGridView 存在了 15 年的"幽灵焦点" 官方 bug**,而且是绑定数据源模式专属:当你点击新增行(带 *)后,再点击任何其他控件(按钮、文本框、菜单),DataGridView 会偷偷在后台把内部焦点从新增行跳到最后一行真实数据,触发RowEnter事件,但UI 界面完全不变(看起来还是选中新增行)。


为什么会这样?(微软的设计缺陷)

  1. 新增行是虚拟行,不是真正的 DataRow,不能持有持久焦点
  2. 当 DataGridView 失去焦点时,微软的代码会强制将焦点 "修正" 到一个真实存在的 DataRow
  3. 但这个修正只改了内部状态,没有更新 UI 高亮、没有滚动条,所以你完全看不出来
  4. 这就是为什么你会看到日志:e.RowIndex=9→ 点击按钮 →e.RowIndex=8,但界面没变化

一行代码彻底修复(永久禁用自动跳转)

在窗体构造函数或 Load 事件里加这一行,从根源上禁止自动跳转

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' 【核心修复】禁止失去焦点时自动跳转到最后一行 DataGridView1.StandardTab = True End Sub

✅ 这个属性是微软专门为这个 bug 留的后门,设置为True后:

  • 点击新增行再点击其他控件,不会再自动跳转到最后一行
  • RowEnter事件不会再被错误触发
  • 所有焦点行为完全符合预期
  • 不影响任何其他功能(包括新增、编辑、删除)

配合你的 RowEnter 事件,最终完整代码

' 全局变量存当前选中的ID(任何地方都能取) Private currentSelectedID As Integer = 0 Private isFormLoaded As Boolean = False Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' 【核心修复】禁止失去焦点时自动跳转到最后一行 DataGridView1.StandardTab = True ' 其他初始化代码... isFormLoaded = True End Sub Private Sub DataGridView1_RowEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.RowEnter If Not isFormLoaded Then Exit Sub If e.RowIndex < 0 Then currentSelectedID = -1 Exit Sub End If ' 1. 底部带*的新增行 → 返回0 If e.RowIndex = DataGridView1.NewRowIndex Then currentSelectedID = 0 Debug.Print($"[{DateTime.Now:HH:mm:ss}] 选中新增行,ID=0") Exit Sub End If ' 2. 未保存的数据源新增行 → 返回0 Dim drv = TryCast(DataGridView1.Rows(e.RowIndex).DataBoundItem, DataRowView) If drv IsNot Nothing AndAlso drv.Row.RowState = DataRowState.Added Then currentSelectedID = 0 Debug.Print($"[{DateTime.Now:HH:mm:ss}] 选中未保存新增行,ID=0") Exit Sub End If ' 3. 正常数据行 → 读取ID Dim val As Object = DataGridView1.Rows(e.RowIndex).Cells("ID").Value currentSelectedID = If(IsDBNull(val) OrElse val Is Nothing, 0, CInt(val)) Debug.Print($"[{DateTime.Now:HH:mm:ss}] 选中行索引={e.RowIndex},ID={currentSelectedID}") End Sub

如果 StandardTab 不生效(极少数情况)

用这个兜底方案,手动保存最后一次选中的行号,完全忽略自动跳转的事件:

Private lastValidRowIndex As Integer = -1 Private Sub DataGridView1_RowEnter(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.RowEnter If Not isFormLoaded Then Exit Sub If e.RowIndex < 0 Then Exit Sub ' 【兜底修复】忽略失去焦点时的自动跳转 If Not DataGridView1.Focused Then ' DataGridView没有焦点时,所有RowEnter事件都是假的,直接用上次保存的值 e.Cancel = True ' 取消这次无效的行切换 Exit Sub End If ' 保存有效的行号 lastValidRowIndex = e.RowIndex ' 后面的判断逻辑和上面完全一样... End Sub

验证方法

  1. 点击新增行(索引 9),日志显示ID=0
  2. 点击 Button1 按钮,不会再触发任何 RowEnter 事件
  3. 再点击 DataGridView,焦点还是在新增行,日志正常显示ID=0
  4. 点击最后一行真实数据(索引 8),日志显示正确的 ID

补充说明

  • 这个 bug 在.NET 2.0 到.NET 10 全版本存在,微软一直没修
  • StandardTab = True还有一个副作用:按 Tab 键会离开 DataGridView,而不是在单元格间循环,这其实是更符合用户习惯的行为
  • 如果你一定要保留 Tab 键在单元格间循环的行为,就用第二个兜底方案
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/11 14:26:53

ChromePass终极指南:3分钟学会从Chrome提取所有密码的完整教程

ChromePass终极指南&#xff1a;3分钟学会从Chrome提取所有密码的完整教程 【免费下载链接】chromepass Get all passwords stored by Chrome on WINDOWS. 项目地址: https://gitcode.com/gh_mirrors/chr/chromepass 在数字时代&#xff0c;密码管理已成为每个技术爱好者…

作者头像 李华
网站建设 2026/6/11 14:26:51

Cursor Free VIP:AI代码编辑器授权绕过技术深度解析与架构设计

Cursor Free VIP&#xff1a;AI代码编辑器授权绕过技术深度解析与架构设计 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached …

作者头像 李华
网站建设 2026/6/11 14:22:05

深入解析PCF85103C-2 I2C EEPROM:硬件设计、驱动开发与可靠性实践

1. 项目概述与芯片定位在嵌入式系统开发中&#xff0c;我们经常需要一种“记忆体”&#xff0c;它能在系统断电后依然牢牢记住一些关键信息&#xff0c;比如设备的配置参数、用户的校准数据、或者运行时的状态标志。这种需求催生了EEPROM&#xff08;电可擦可编程只读存储器&am…

作者头像 李华
网站建设 2026/6/11 14:22:04

53:故障排查思路1:机台连不上EAP完整分层排查

53&#xff1a;故障排查思路1&#xff1a;机台连不上EAP完整分层排查 一、本课学习目标 建立标准化四层分层排查模型&#xff0c;解决设备OFFLINE无法联机问题区分物理层、网络层、HSMS传输层、SECS应用层各类不通故障特征掌握Ping、端口探测、抓包、日志四种工具定位问题梳理量…

作者头像 李华