vb.net 在 datagridview 更新后保持关注行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31469545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 19:17:52  来源:igfitidea点击:

Keep focus on row after datagridview update

vb.netdatagridviewfocus

提问by FiN

I'm creating an VB windows application. The point of the application is a simple DataGridViewwhere I'm fetching a Viewfrom a SQL Server database.

我正在创建一个 VB windows 应用程序。应用程序的要点很简单DataGridView,我View从 SQL Server 数据库中获取 a 。

The DataGridViewis refreshed every second so I could see new data income in my GridView.

DataGridView是每秒钟刷新一次,所以我可以看到我的GridView新的数据收入。

The problem is keeping focus on row after the refresh. I need the solution, where after I click a row, or a cell it keeps me on it even after the refresh.

问题是在刷新后保持对行的关注。我需要解决方案,在我单击一行或一个单元格后,即使在刷新后它也会让我保持在它上面。

Here is my code:

这是我的代码:

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

回答by M463

I've solved a similar problem in the past by storing the indexes of the selected cell in a variable before doing the refresh, so I'm able to restore the selection by calling DataGridView.Rows(selRow).Cells(selCol).Selected = Trueafter the update.

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



Edit - Sample Code:

编辑 - 示例代码:

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

致后来的读者:
请看一下 Edit#2,其中我描述了一种更好的方法来重新选择上一个选定的单元格!

Sample Code:

示例代码:

'   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

Please note:

请注意:

  • This procedure requires you to add the rows in the exact same order that you have added them before the update, as only the .Indexof the selected row is stored in the variable. If you readding the rows in a different order, then not the same row but the row at the same positionwill be selected after the refresh.
  • You should add check if there is a selected row at all (to prevent a NullPointerException) and if there are "enough" rows in the DataGridViewafterthe refresh, to prevent an IndexOutOfBoundsException.
  • This only works if the DataGridView1.SelectionModeis to something that actually selects rows, like FullRowSelect.
  • Don't forget to clear any existing rows before adding new ones by updating (only if you always reloading all rows).
  • 此过程要求您以与更新前添加行完全相同的顺序添加行,因为只有.Index选定行的 存储在变量中。如果以不同的顺序读取行,则刷新后将选择的不是同一行而是同一位置的行
  • 您应该添加检查是否有选定的行(以防止 a NullPointerException)以及刷新DataGridView是否有“足够”的行,以防止IndexOutOfBoundsException.
  • 这仅适用DataGridView1.SelectionMode于实际选择行的内容,例如FullRowSelect.
  • 不要忘记在通过更新添加新行之前清除任何现有行(仅当您总是重新加载所有行时)。


Edit 2 - RowHeader triangle and accidental MultiSelect

编辑 2 - RowHeader 三角形和意外多选

As stated in the comments below, there was an odd behavior that would lead to an accidental MultiSelect, if the user holds down the mouse button past the refresh cycle. Also, the RowHeader triangle was not set to the correct row.

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

After some research I found a solution to this behavior. Instead of setting the .Selected-property of a given cell to True, set the .CurrentCell-property of the DataGridViewto the cell you would like to select!

经过一番研究,我找到了解决这种行为的方法。相反设置的.Selected特定细胞的-property来True,设置.CurrentCell的-propertyDataGridView的细胞,你想选择!

In code, this means changing

在代码中,这意味着改变

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

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

to

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

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

and there you go. :-)

你去吧。:-)

回答by Graffito

Before Fill, store the CurrentRow values and currenCell column:

在 Fill 之前,存储 CurrentRow 值和 currentCell 列:

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

After Fill, search the row corresponding to stored values:

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

Note: the "For/While" loop coding is perhaps not optimal because it results from automatic conversion from C# to vb.net.

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

回答by Fikalefaza

C# fix code , next reload pattern

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;