sharp
sharp

Reputation: 1211

Keep focus on row after datagridview update

I'm creating an VB windows application. The point of the application is a simple DataGridView where I'm fetching a View from a SQL Server database.

The DataGridView is refreshed every second so I could see new data income in my 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

Upvotes: 0

Views: 9310

Answers (3)

Fikalefaza
Fikalefaza

Reputation: 1

C# fix code , next reload pattern

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;

Upvotes: 0

M463
M463

Reputation: 2183

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 = True after the update.


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!

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 .Index of 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 position will 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 DataGridView after the refresh, to prevent an IndexOutOfBoundsException.
  • This only works if the DataGridView1.SelectionMode is 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).

Edit 2 - RowHeader triangle and accidental MultiSelect

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.

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 DataGridView to the cell you would like to select!

In code, this means changing

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

to

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

and there you go. :-)

Upvotes: 3

Graffito
Graffito

Reputation: 1718

Before Fill, store the CurrentRow values and currenCell column:

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:

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.

Upvotes: 2

Related Questions