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
关键逻辑说明
- 保存主键信息:刷新前检查DataGridView是否有选中行,若有则提取四列主键的字符串值,使用
?.ToString()避免空引用异常。 - 刷新数据:调用原有的
population方法重新加载数据表。 - 恢复选中状态:遍历新的DataTable,逐一匹配四列主键值,找到对应行后设置为选中状态,并通过
FirstDisplayedScrollingRowIndex将该行滚动到可视区域。
注意事项
- 确保DataGridView的列名与数据库列名完全一致,否则会出现单元格找不到的错误。
- 如果主键列包含非字符串类型(如数字),需要调整类型转换逻辑,避免字符串匹配出错。
- 建议在异常捕获块中添加错误提示或日志记录,便于排查数据加载失败的问题。
内容的提问来源于stack exchange,提问作者roy
相关产品推荐
相关产品推荐

