datagridview 更新后继续关注行

Keep focus on row after datagridview update

我正在创建一个 VB windows 应用程序。该应用程序的重点是一个简单的 DataGridView,我从 SQL 服务器数据库中获取 View

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

我过去解决了类似的问题,方法是在刷新之前将 selected 单元格的索引存储在一个变量中,因此我能够恢复 selection通过在更新后调用 DataGridView.Rows(selRow).Cells(selCol).Selected = True


编辑 - 示例代码:

To later readers:
Please take a look at Edit#2 where I describe a better method to re-select the previous selected cell!

示例代码:

'   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

请注意:

  • 此过程要求您按照更新前添加行的顺序添加行,因为只有 selected 行的 .Index 存储在变量中。如果您以不同的顺序读取行,那么刷新后 select 将 select 编辑 相同位置 的行。
  • 您应该添加检查是否有 selected 行(以防止 NullPointerException)以及 DataGridView [=49] 中是否有“足够”的行=]在刷新后,防止出现IndexOutOfBoundsException.
  • 这仅在 DataGridView1.SelectionMode 指向实际 select 行的内容时有效,例如 FullRowSelect
  • 在通过更新添加新行之前,不要忘记清除任何现有行(仅当您始终重新加载所有行时)。

编辑 2 - RowHeader 三角形和意外的 MultiSelect

如以下评论所述,如果用户按住鼠标按钮超过刷新周期,会出现一种奇怪的行为,会导致意外的多选。此外,RowHeader 三角形未设置为正确的行。

经过一番研究,我找到了解决此问题的方法。不要将给定单元格的 .Selected-属性 设置为 True,而是将 DataGridView.CurrentCell-属性 设置为您要设置的单元格想select!

在代码中,这意味着改变

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

Fill后,搜索存储值对应的行:

Dim i As Integer = 0
While i < DataGridView1.Rows.Count AndAlso currentValues IsNot Nothing
    Dim areIdentical As Boolean = True
    Dim j As Integer = 0
    While j < DataGridView1.Columns.Count AndAlso areIdentical
        areIdentical = DataGridView1.Rows(i).Cells(j).Value = currentValues(j)
        j += 1
    End While
    If areIdentical Then
        DataGridView1.CurrentCell = DataGridView1.Rows(i).Cells(currentColumnIndex)
        currentValues = Nothing
    End If
    i += 1
End While

注意:"For/While" 循环编码可能不是最佳的,因为它是从 C# 自动转换为 vb.net 的结果。

C# 修复代码,下一个重新加载模式

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;