Hi Everyone,
Below is some VB .NET 2.0 code that you should be able to paste in to a form and run. It demonstrates the basics of an application I'm working on that uses BackgroundWorkers to continuously monitor an application on servers, and updates a table (Table2). For demonstration purposes, the code below just changes the time column on each row. Then, at a specified interval (typically one or a few seconds), Table2 will be merged into Table1, which is bound to a DataGridView.
The behavior I want is for the grid to not automatically scroll to the selected row when the table merge occurs. I have tried a number of things and nothing is working perfectly. The closest I've gotten is to get the FirstDisplayedScrollingRowIndex before the merge, and then set it back after the merge. However, this results in the scrollbar stopping when the table merge occurs if the user is dragging it, and the mouse button has to come up before the user can grab the scrollbar again.
Another problem is that the vertical scrollbar gets totally fudged up if you set the form width so that the horizontal scrollbar appears and you click the down arrow quickly several times.
Any ideas on how to address these issues would be greatly appreciated. Ideally, the user's row selection and scrolling will never be changed or interrupted. Please don't bother suggesting creating my own scrollbar and controlling it all programatically. I'm aware of that option but am looking for something more n00b programmer friendly.
Thanks!
Public Class Form1
Public Table1 As DataTable
Public Table2 As New DataTable
Public DataGridView1 As New DataGridView
Dim WithEvents BackgroundWorker1 As New System.ComponentModel.BackgroundWorker
Dim WithEvents Timer1 As New Timer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim DataSet1 As New DataSet
Dim bindSource As New BindingSource
Dim counterX As Short
Dim pKey(1) As DataColumn
Timer1.Interval = 1000
Timer1.Enabled = False
DataGridView1.Parent = Me
DataGridView1.Dock = DockStyle.Fill
DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
Me.Show()
Me.Focus()
DataGridView1.Refresh()
Table1 = DataSet1.Tables.Add()
Table1.Columns.Add( "Column1")
Table1.Columns.Add( "Column2")
Table1.Columns.Add( "Column3")
Table1.Columns.Add( "Column4")
Table1.Columns.Add( "Time")
pKey(0) = Table1.Columns(0)
Table1.PrimaryKey = pKey
DataGridView1.DataSource = bindSource
bindSource.DataSource = DataSet1
bindSource.DataMember = "Table1"
For counterX = 1 To 50
Table1.Rows.Add( "Column1-Row" & counterX, "Column2-Row" & counterX, "Column3-Row" & counterX, "Column1-Row" & counterX, Now)
Next
DataSet1.Tables.Add(Table2)
Table2 = Table1.Copy()
DataGridView1.Refresh()
Timer1.Enabled = True
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim rowItem As DataRow
Do
SyncLock Table2
For Each rowItem In Table2.Rows
rowItem.Item( "Time") = Now
Next
End SyncLock
System.Threading.Thread.Sleep(1000)
Loop
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim hOffset As Integer
hOffset = DataGridView1.HorizontalScrollingOffset
SyncLock Table2
Table1.Merge(Table2, False)
End SyncLock
DataGridView1.HorizontalScrollingOffset = hOffset
End Sub
End Class
Windows Forms14
|