Vb.net 在datagridview更新后保持对行的关注

Vb.net 在datagridview更新后保持对行的关注,vb.net,datagridview,focus,Vb.net,Datagridview,Focus,我正在创建一个VB windows应用程序。应用程序的要点是一个简单的DataGridView,其中我从SQLServer数据库获取视图 DataGridView每秒刷新一次,这样我就可以在GridView中看到新的数据收入 问题在于刷新后将焦点保持在行上。我需要解决方案,在我单击一行或一个单元格后,即使在刷新之后,它也会使我保持在该行或单元格上 这是我的密码: Public Class Form1 Private Sub Form1_Load(sender As Object, e A

我正在创建一个VB windows应用程序。应用程序的要点是一个简单的
DataGridView
,其中我从SQLServer数据库获取
视图

DataGridView
每秒刷新一次,这样我就可以在GridView中看到新的数据收入

问题在于刷新后将焦点保持在行上。我需要解决方案,在我单击一行或一个单元格后,即使在刷新之后,它也会使我保持在该行或单元格上

这是我的密码:

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'Refresh every 1 sec
        Dim timer As New Timer()
        timer.Interval = 1000
        AddHandler timer.Tick, AddressOf timer_Tick
        timer.Start()
        'TODO: This line of code loads data into the 'XYZDataSet.view1' table. You can move, or remove it, as needed.
        Me.View1TableAdapter.Fill(Me.XYZDataSet.view1)
    End Sub

    Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick
    End Sub

    Private Sub DataGridView1_CellFormatting(ByVal sender As Object, ByVal e As DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
        For i As Integer = 0 To Me.DataGridView1.Rows.Count - 1
            If Me.DataGridView1.Rows(i).Cells("DayTillDelivery").Value <= 30 Then
                Me.DataGridView1.Rows(i).Cells("DayTillDelivery").Style.ForeColor = Color.Red
            End If
        Next
    End Sub

    Private Sub timer_Tick(ByVal sender As Object, ByVal e As EventArgs)
        'Calling refresh after 1 second and updating the data
        Me.DataGridView1.Refresh()
        Me.View1TableAdapter.Fill(Me.XYZDataSet.view1)
    End Sub
End Class
公共类表单1
私有子表单1_Load(发送方作为对象,e作为事件参数)处理MyBase.Load
'每1秒刷新一次
将计时器变暗为新计时器()
计时器。间隔=1000
AddHandler timer.Tick,timer\u Tick的地址
timer.Start()
'TODO:这行代码将数据加载到'XYZDataSet.view1'表中。您可以根据需要移动或删除它。
Me.View1TableAdapter.Fill(Me.XYZDataSet.view1)
端接头
私有子DataGridView1\u CellContentClick(发送者作为对象,e作为DataGridViewCellEventArgs)处理DataGridView1.CellContentClick
端接头
私有子DataGridView1u CellFormatting(ByVal sender作为对象,ByVal e作为DataGridViewCellFormattingEventArgs)处理DataGridView1.CellFormatting
对于i As Integer=0到Me.DataGridView1.Rows.Count-1

如果Me.DataGridView1.Rows(i).Cells(“DayTillDelivery”).Value我以前解决过类似的问题,在刷新之前将所选单元格的索引存储在一个变量中,因此我可以在更新之后调用
DataGridView.Rows(selRow).Cells(selCol).selected=True
来恢复选择


编辑-示例代码: 给以后的读者:
请看一下Edit#2,我在这里介绍了一种更好的方法来重新选择以前选择的单元格

示例代码:

'   Variables for remembering the indexes of the selected cell
Dim selRow As Integer
Dim selCol As Integer

'   Check if there is a selected cell to prevent NullPointerException
If DataGridView1.SelectedCells().Count > 0 Then
    selRow = DataGridView1.CurrentCell.RowIndex
    selCol = DataGridView1.CurrentCell.ColumnIndex
End If

'   Dummy "update"
'   don't forget to clear any existing rows before adding the new bunch (only if you always reloading all rows)!
DataGridView1.Rows.Clear()
For index = 1 To 20
    DataGridView1.Rows.Add()
Next

'   Check if there are "enough" rows after the update, 
'   to prevent setting the selection to an rowindex greater than the Rows.Count - 1 which would 
'   cause an IndexOutOfBoundsException
If (DataGridView1.Rows.Count - 1) > selRow Then
    '   Clear selection and then reselect the cell that was selected before by index
    DataGridView1.ClearSelection()
    '   For the next line of code, there is a better solution in Edit #2!
    DataGridView1.Rows(selRow).Cells(selCol).Selected = True       
End If
请注意:

  • 此过程要求您按照更新前添加行的顺序添加行,因为变量中只存储所选行的
    .Index
    。如果以不同的顺序读取行,则刷新后将选择不相同的行,而是位于相同位置的行
  • 您应该添加检查,检查是否有选中的行(以防止出现
    NullPointerException
    ),以及刷新后
    DataGridView
    中是否有“足够”的行,以防止出现
    IndexOutOfBoundsException
  • 这仅在
    DataGridView1.SelectionMode
    是实际选择行的对象时有效,如
    FullRowSelect
  • 在通过更新添加新行之前,不要忘记清除任何现有行(仅当您总是重新加载所有行时)

编辑2-行标题三角形和意外多选 如下面的评论所述,如果用户在刷新周期结束后按住鼠标按钮,则会出现一种奇怪的行为,导致意外的多选。此外,RowHeader三角形未设置为正确的行

经过一些研究,我找到了解决这种行为的方法。不要将给定单元格的
.Selected
-属性设置为
True
,而是将
DataGridView
.CurrentCell
-属性设置为要选择的单元格

在代码中,这意味着改变

DataGridView1.Rows(selRow).Cells(selCol).Selected=True

DataGridView1.CurrentCell=DataGridView1.Rows(selRow)。Cells(selCol)


这就是你想要的。:-)

我以前解决过一个类似的问题,在刷新之前将所选单元格的索引存储在一个变量中,因此我可以在更新后调用
DataGridView.Rows(selRow).Cells(selCol).selected=True
来恢复所选内容


编辑-示例代码: 给以后的读者:
请看一下Edit#2,我在这里介绍了一种更好的方法来重新选择以前选择的单元格

示例代码:

'   Variables for remembering the indexes of the selected cell
Dim selRow As Integer
Dim selCol As Integer

'   Check if there is a selected cell to prevent NullPointerException
If DataGridView1.SelectedCells().Count > 0 Then
    selRow = DataGridView1.CurrentCell.RowIndex
    selCol = DataGridView1.CurrentCell.ColumnIndex
End If

'   Dummy "update"
'   don't forget to clear any existing rows before adding the new bunch (only if you always reloading all rows)!
DataGridView1.Rows.Clear()
For index = 1 To 20
    DataGridView1.Rows.Add()
Next

'   Check if there are "enough" rows after the update, 
'   to prevent setting the selection to an rowindex greater than the Rows.Count - 1 which would 
'   cause an IndexOutOfBoundsException
If (DataGridView1.Rows.Count - 1) > selRow Then
    '   Clear selection and then reselect the cell that was selected before by index
    DataGridView1.ClearSelection()
    '   For the next line of code, there is a better solution in Edit #2!
    DataGridView1.Rows(selRow).Cells(selCol).Selected = True       
End If
请注意:

  • 此过程要求您按照更新前添加行的顺序添加行,因为变量中只存储所选行的
    .Index
    。如果以不同的顺序读取行,则刷新后将选择不相同的行,而是位于相同位置的行
  • 您应该添加检查,检查是否有选中的行(以防止出现
    NullPointerException
    ),以及刷新后
    DataGridView
    中是否有“足够”的行,以防止出现
    IndexOutOfBoundsException
  • 这仅在
    DataGridView1.SelectionMode
    是实际选择行的对象时有效,如
    FullRowSelect
  • 在通过更新添加新行之前,不要忘记清除任何现有行(仅当您总是重新加载所有行时)

编辑2-行标题三角形和意外多选 如下面的评论所述,如果用户在刷新周期结束后按住鼠标按钮,则会出现一种奇怪的行为,导致意外的多选。此外,RowHeader三角形未设置为正确的行

经过一些研究,我找到了解决这种行为的方法。不要将给定单元格的
.Selected
-属性设置为
True
,而是将
DataGridView
.CurrentCell
-属性设置为要选择的单元格

在代码中,这意味着改变

DataGridView1.Rows(selRow).Cells(selCol).Selected=True

DataGridView1.CurrentCell=DataGridView1.Rows(selRow)。Cells(selCol)


这就是你想要的。:-)

填充前,存储CurrentRow值和currenCell列:

Dim currentColumnIndex As Integer = 0 ;
Dim currentValues As List(Of Object) = If(DataGridView1.CurrentRow Is Nothing, Nothing, New List(Of Object)())
If currentValues IsNot Nothing Then
    For i As Integer = 0 To DataGridView1.Columns.Count - 1
        currentValues.Add(DataGridView1.CurrentRow.Cells(i).Value)
    Next
currentColumnIndex = DataGridView1.CurrentCell.ColumnIndex;
End If
填充后,搜索对应的行
if (dataGridView7.SelectedCells.Count > 0)
{
    //MessageBox.Show(selcell + "------"+dataGridView7.CurrentCell.ColumnIndex.ToString());
    if (selcell > 0 && dataGridView7.CurrentCell.ColumnIndex==0) {  }else
    {
        selrow = dataGridView7.CurrentCell.RowIndex;
        selcell = dataGridView7.CurrentCell.ColumnIndex;
    }

}

loaddataJobsall();
dataGridView7.ClearSelection();
dataGridView7.Rows[selrow].Cells[selcell].Selected = true;