DataGrid如何实现搜索跳转目标记录且保留全量数据供浏览
核心问题排查
你现有代码无法实现需求的原因有3个:
- SQL逻辑完全错误:
WHERE IDSIZE <> 输入值的写法会直接把和输入尺寸相等的记录排除出查询结果,和「保留全部记录」的需求完全相反。 - 缺失定位逻辑:数据加载排序后没有任何跳转选中目标行的代码,控件默认会从第一行开始显示。
- 资源释放逻辑有缺陷:数据库连接关闭逻辑写在Try块中,一旦查询中途报错,连接会一直占用无法释放。
实现代码
推荐优先用「首次加载全量数据+本地定位」的方案,不需要每次搜索都查库,响应速度更快。
方案1:本地定位(推荐)
首先在窗体加载时拉取全量数据并按尺寸升序排列,后续搜索直接在已加载的行中匹配定位:
' 窗体级数据库连接对象,连接字符串建议存放在配置文件中,不要硬编码 Private conn As New OleDb.OleDbConnection("你的数据库连接字符串") Private Sub Form_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' 初始化加载全量模具数据 LoadAllDieRecords() End Sub ''' <summary> ''' 加载全量模具数据,按IDSIZE升序排列 ''' </summary> Private Sub LoadAllDieRecords() Try DataGridRecords.Rows.Clear() conn.Open() ' 直接查询全量数据,在数据库端完成排序,性能优于客户端排序 Dim cmd As New OleDb.OleDbCommand("SELECT * FROM tblDies ORDER BY IDSIZE ASC", conn) Dim dr = cmd.ExecuteReader() While dr.Read() DataGridRecords.Rows.Add( dr.Item("ID"), dr.Item("DIENUMBER"), dr.Item("DESCRIPT"), dr.Item("OLDNUMBER"), dr.Item("CODE"), dr.Item("QUANTITY"), dr.Item("IDSIZE"), dr.Item("ODSIZE"), dr.Item("HEIGHT"), dr.Item("FLANGE HT"), dr.Item("FLANGE DIA"), dr.Item("CuRef"), dr.Item("CUTEL"), dr.Item("CuContact"), dr.Item("Price-selling"), dr.Item("P/no"), dr.Item("Stoksize"), dr.Item("Material"), dr.Item("Shore"), dr.Item("DieChkd"), dr.Item("DIECOST"), dr.Item("DATE"), dr.Item("REMARKS"), dr.Item("PRREF") ) End While dr.Close() Catch ex As Exception MsgBox(ex.Message) Finally ' 无论查询是否报错,都确保连接关闭释放 If conn.State = ConnectionState.Open Then conn.Close() End Try End Sub ''' <summary> ''' 搜索按钮点击事件,定位到目标尺寸行 ''' </summary> Private Sub btnSearch_Click(sender As Object, e As EventArgs) Handles btnSearch.Click ' 校验输入是否为合法数值 Dim targetSize As Decimal If Not Decimal.TryParse(txtIdSize.Text.Trim(), targetSize) Then MsgBox("请输入有效的尺寸数值") txtIdSize.Focus() Return End If DataGridRecords.ClearSelection() Dim targetRowIndex As Integer = -1 ' 遍历所有行,因为数据已经按升序排列,第一个IDSIZE>=目标值的行就是要定位的行 For Each row As DataGridViewRow In DataGridRecords.Rows If row.IsNewRow Then Continue For ' 跳过DataGridView的新增空白行 Dim currentSize As Decimal If Decimal.TryParse(row.Cells(6).Value?.ToString(), currentSize) AndAlso currentSize >= targetSize Then targetRowIndex = row.Index Exit For End If Next If targetRowIndex >= 0 Then ' 选中目标行,同时滚动到可视区域 DataGridRecords.Rows(targetRowIndex).Selected = True DataGridRecords.FirstDisplayedScrollingRowIndex = targetRowIndex Else MsgBox("未找到大于等于输入尺寸的记录") End If End Sub
方案2:每次搜索重新拉取全量数据后定位
如果业务要求每次搜索必须同步数据库最新数据,可以直接修改原有search过程,去掉错误的过滤条件,加载完成后追加定位逻辑:
Sub search() Dim targetSize As Decimal If Not Decimal.TryParse(txtIdSize.Text.Trim(), targetSize) Then MsgBox("请输入有效的尺寸数值") Return End If Try DataGridRecords.Rows.Clear() conn.Open() ' 移除错误的WHERE条件,查询全量数据并在数据库端排序 Dim cmd As New OleDb.OleDbCommand("SELECT * FROM tblDies ORDER BY IDSIZE ASC", conn) dr = cmd.ExecuteReader While dr.Read DataGridRecords.Rows.Add( dr.Item("ID"), dr.Item("DIENUMBER"), dr.Item("DESCRIPT"), dr.Item("OLDNUMBER"), dr.Item("CODE"), dr.Item("QUANTITY"), dr.Item("IDSIZE"), dr.Item("ODSIZE"), dr.Item("HEIGHT"), dr.Item("FLANGE HT"), dr.Item("FLANGE DIA"), dr.Item("CuRef"), dr.Item("CUTEL"), dr.Item("CuContact"), dr.Item("Price-selling"), dr.Item("P/no"), dr.Item("Stoksize"), dr.Item("Material"), dr.Item("Shore"), dr.Item("DieChkd"), dr.Item("DIECOST"), dr.Item("DATE"), dr.Item("REMARKS"), dr.Item("PRREF") ) End While dr.Close() ' 追加定位逻辑 DataGridRecords.ClearSelection() Dim targetRowIndex As Integer = -1 For Each row As DataGridViewRow In DataGridRecords.Rows If row.IsNewRow Then Continue For Dim currentSize As Decimal If Decimal.TryParse(row.Cells(6).Value?.ToString(), currentSize) AndAlso currentSize >= targetSize Then targetRowIndex = row.Index Exit For End If Next If targetRowIndex >= 0 Then DataGridRecords.Rows(targetRowIndex).Selected = True DataGridRecords.FirstDisplayedScrollingRowIndex = targetRowIndex Else MsgBox("未找到大于等于输入尺寸的记录") End If Catch ex As Exception MsgBox(ex.Message) Finally If conn.State = ConnectionState.Open Then conn.Close() End Try End Sub
关键说明
- 定位功能核心依赖DataGridView的
FirstDisplayedScrollingRowIndex属性,设置该属性可以直接控制控件滚动到对应行索引的位置,配合Selected属性选中行即可实现不筛选数据的跳转定位效果。 - 不建议使用字符串拼接方式构造SQL语句,后续如果需要增加查询条件,优先使用参数化查询,避免特殊字符引发SQL错误或注入风险。
- 尺寸字段判断用
>=匹配,刚好符合「有精确值就定位到精确值,没有就定位到第一个比输入值大的记录」的需求。
内容的提问来源于stack exchange,提问作者Lloyd
相关产品推荐
相关产品推荐

