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

VB.NET中不使用BindingSource,DataGridView刷新后保留选中行位置

VB.NET实现DataGridView刷新后保留选中行(无BindingSource、复合主键场景)

实现方案

由于你的表使用CODEPRODUCT、BARCODE、COLORCODE、SIZE四列作为复合主键,刷新时需要先记录当前选中行的主键信息,待数据重新加载后通过匹配主键恢复选中状态。以下是修改后的完整代码:

Private WithEvents dt As New DataTable
Dim dataAdapter As OleDbDataAdapter
Dim GetConnectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\demo.accdb;Persist Security Info=False;"

Private Sub population()
    Try
        dt = New DataTable
        Dim query As String = "SELECT * from stocks"
        Using con As OleDbConnection = New OleDbConnection(GetConnectionString)
            Using cmd As OleDbCommand = New OleDbCommand(query, con)
                Using da As New OleDbDataAdapter(cmd)
                    da.Fill(dt)
                    DataGridView1.DataSource = dt
                    Me.DataGridView1.Refresh()
                End Using
            End Using
        End Using
    Catch ex As Exception
        ' 建议添加异常日志或提示,方便排查问题
        ' MsgBox("加载数据失败:" & ex.Message)
    End Try
End Sub

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Me.DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
    Me.DataGridView1.MultiSelect = False
    population()
End Sub

Private Sub Btnrefresh_Click(sender As Object, e As EventArgs) Handles Btnrefresh.Click
    ' 1. 保存当前选中行的主键值
    Dim selectedCodeProduct As String = Nothing
    Dim selectedBarcode As String = Nothing
    Dim selectedColorCode As String = Nothing
    Dim selectedSize As String = Nothing

    If DataGridView1.SelectedRows.Count > 0 Then
        Dim selectedRow = DataGridView1.SelectedRows(0)
        selectedCodeProduct = selectedRow.Cells("CODEPRODUCT").Value?.ToString()
        selectedBarcode = selectedRow.Cells("BARCODE").Value?.ToString()
        selectedColorCode = selectedRow.Cells("COLORCODE").Value?.ToString()
        selectedSize = selectedRow.Cells("SIZE").Value?.ToString()
    End If

    ' 2. 刷新数据
    population()

    ' 3. 恢复选中行(仅当之前有选中行时执行)
    If Not String.IsNullOrEmpty(selectedCodeProduct) AndAlso Not String.IsNullOrEmpty(selectedBarcode) AndAlso Not String.IsNullOrEmpty(selectedColorCode) AndAlso Not String.IsNullOrEmpty(selectedSize) Then
        For Each row As DataRow In dt.Rows
            If row("CODEPRODUCT").ToString() = selectedCodeProduct AndAlso _
               row("BARCODE").ToString() = selectedBarcode AndAlso _
               row("COLORCODE").ToString() = selectedColorCode AndAlso _
               row("SIZE").ToString() = selectedSize Then
                ' 找到匹配行,设置选中并滚动到可视区域
                Dim gridRow = DataGridView1.Rows(DataGridView1.Rows.Cast(Of DataGridViewRow).FirstOrDefault(Function(r) 
                    r.Cells("CODEPRODUCT").Value.ToString() = selectedCodeProduct AndAlso _
                    r.Cells("BARCODE").Value.ToString() = selectedBarcode AndAlso _
                    r.Cells("COLORCODE").Value.ToString() = selectedColorCode AndAlso _
                    r.Cells("SIZE").Value.ToString() = selectedSize).Index)
                gridRow.Selected = True
                DataGridView1.FirstDisplayedScrollingRowIndex = gridRow.Index
                Exit For
            End If
        Next
    End If
End Sub

关键逻辑说明

  1. 保存主键信息:刷新前检查DataGridView是否有选中行,若有则提取四列主键的字符串值,使用?.ToString()避免空引用异常。
  2. 刷新数据:调用原有的population方法重新加载数据表。
  3. 恢复选中状态:遍历新的DataTable,逐一匹配四列主键值,找到对应行后设置为选中状态,并通过FirstDisplayedScrollingRowIndex将该行滚动到可视区域。

注意事项

  • 确保DataGridView的列名与数据库列名完全一致,否则会出现单元格找不到的错误。
  • 如果主键列包含非字符串类型(如数字),需要调整类型转换逻辑,避免字符串匹配出错。
  • 建议在异常捕获块中添加错误提示或日志记录,便于排查数据加载失败的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:36:06