Controlling Scrolling  
Author Message

PostPosted: Windows Forms Data Controls and Databinding, Controlling Scrolling Top

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.


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




Table1 = DataSet1.Tables.Add()






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)



Table2 = Table1.Copy()


Timer1.Enabled = True


End Sub

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

Dim rowItem As DataRow


SyncLock Table2

For Each rowItem In Table2.Rows

rowItem.Item("Time") = Now


End SyncLock



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 Forms9  

PostPosted: Windows Forms Data Controls and Databinding, Controlling Scrolling Top

It never fails--I spend 10 hours struggling with something, finally swallow my pride and post a request for help, and then figure it out ten minutes later.

I found that setting the vetical scrollbar mouse capture to false and recapturing it after the table merge works pretty well.

If DataGridView1.Controls(1).Capture = True Then

DataGridView1.Controls(1).Capture = False

mouseCaptured = True

End If

'do the table merge here

If mouseCaptured = True Then

DataGridView1.Controls(1).Capture = True

End If


PostPosted: Windows Forms Data Controls and Databinding, Controlling Scrolling Top

I am doing something similar in C#.. How do I capture a datagridview's vertical scrollbars in C#

I tried to capture = false the entire datagridview before filling my dataset, and then recapture it again. Didn't seem to work for me.

here is a link to my post: PostID=1074549&SiteID=1 describing my situation in detail.

Any help would be appreciated.