Reputation: 1211
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
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
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.
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:
.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.NullPointerException
) and if there are "enough" rows in the DataGridView
after the refresh, to prevent an IndexOutOfBoundsException
.DataGridView1.SelectionMode
is to something that actually selects rows, like FullRowSelect
.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
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