Question

halovalo on Fri, 13 May 2016 10:56:26


Hi all!

I was searching  for solution now for a long time and trying different things but no one seems to have (or is bothered by) the same problem. Usually there's some hidden scrollbar problem etc but that all works fine for me.

I have a datagridview with many columns. First two are freezed. Scroll works ok while the mouse is in line with the scroll bar and in line with the first few upper rows.

The problem starts when the mous moves even further upwards. At some point it resets the horizontal scrollbar and the columns back to the point of scrollbar.Mousedown...which I don't know how to handle.

datagridview.mousemove is not active because technically the event is still datagridview.scroll.

datagridview.mousehover shows same behaviour.

I think I'd have to somehow exit the scroll event at this particular point or enable scrolling even if mouse is futher up north. Perhaps there's another solution I can't think of.

I thank you for all suggestions in advance.


Sponsored



Replies

IronRazerz on Fri, 13 May 2016 20:06:14


 I am not sure if i understand what you mean.  Do you mean that the scroll position jumps back to the original starting spot when the mouse moves above, below, or to the side of the scrollbar by a few inches.  If so,  then that is just the common behavior of a scroll-able window.  That happens in any scroll-able window.  Try it in an AutoScroll panel or even in Notepad,  it does the same thing.

 If that is not what you mean,  then you will need to create a small example that reproduces the problem that we can test.



If you say it can`t be done then i`ll try it

halovalo on Fri, 13 May 2016 21:03:19


I also suspected the datagridview's built this way...

although I have a slightly different problem.

I have (for now) a table with 14 columns. First two are frozen. Datagridview stretches throughout the screen and the last three cols are hidden behind the vertical scroll...so the horizontal scroll is also active.

If I hold the left button on the HScroll thumb and slowly move it to the right all is well but...

Not all users on this world are slow... so I tested some fast left to right scrolling and my mouse went a bit to far upwards not just to the right...that's when I noticed this behavior. For a few rows upwards everything is ok... but as you continue right and up at some point the same thing happens as in your picture. This is probably the way DGV works but I have some panels and textboxes that are supposed to get moved on scroll. At this point they get scrambled... so I was searching a way to either suppress the standard DGV behavior or catch an event that gets fired at that particular time. (unfortunately to no avail).

The thing that bothers me the most is that solution is probably very simple.

Mr. Monkeyboy on Sat, 14 May 2016 00:51:33


It's possible you could set the DataGridView on a Panel and use the Panels scrollbars.

Then you would use an event of some type for the DataGridView such that when that event fires you would set the DataGridViews size such that the DataGridView would not display any scrollbars but the Panel would since the DataGridView would be larger than the Panel. I don't believe the Panel would have this issue with its scrollbars.

Also see How can I set the distance from last row to the end of datagridview ? which is a workaround for another issue with the DGV and not specific to what you need now but may have some insight into how to set the DGV's size perhaps relative to its ClientSize which should be the size of all the columns and rows and then make the DGV larger than that clientsize to some degree I guess. Or maybe exactly the size of its clientsize or the exact size of its client size + whatever size its borders are if it has any.

Also see DataGridView Events and maybe use the ClientSizeChanged event to alter the DGV's size.


La vida loca

halovalo on Mon, 16 May 2016 09:42:31


I'm a bit confused as to why use additional panel if datagridview already owns scrollbars?

Now I found out that .HorizontalScrollingOffset solves a half of the problem. At least columns go back to the last position of the scrollbar. However the bar itself is shot to its starting position.

How can I programmatically set the scrollbars (thumb) position in datagridview?

Mr. Monkeyboy on Mon, 16 May 2016 12:09:36


I'm a bit confused as to why use additional panel if datagridview already owns scrollbars?

Now I found out that .HorizontalScrollingOffset solves a half of the problem. At least columns go back to the last position of the scrollbar. However the bar itself is shot to its starting position.

How can I programmatically set the scrollbars (thumb) position in datagridview?

Since you were having issues using DGV scrollbars then I suggested that possibility. If you set the ClientSize of the DataGridView so that the width of all columns and height to the column header and all rows then the DGV doesn't display any scrollbars since the DGV is then the size of everything it contains as far as column header height, width and all rows heights. Then if it is a control of a Panel you can use the Panels scrollbars since the Panel can be set to use scrollbars if one of its child controls is larger than its display rectangle. Although I tried that I couldn't figure out an event to use if you updated the DGV and needed to resize its ClientSize. Probably cause I'm Lazy!

Anyhow the below two lines of code will work for scrolling a DGV vertically I believe but didn't test it. You can also get the FirstDisplayedScrollingRowIndex (a property of DGV).

DataGridView1.FirstDisplayedScrollingRowIndex -= 1
DataGridView1.FirstDisplayedScrollingRowIndex += 1

The below code is more "intimate" in that the DGV has a VScrollBar as a Child Control (I think it's called a Child Control) which I never knew but somebody at Experts Exchange where I got the code knew. You can set the VScrollBars value but unless you send a message for a Mouse Left Down followed by a Mouse Left Up to the VScrollBar slider button after setting the value the DGV will not scroll even though the VScrollBars button moves.

Update: I altered the code because I noticed that the VScrollBar was never receiving the Mouse Left Down/Mouse Left Up message to its VScrollBar slider. Therefore the slider wouldn't focus until a manual MLD/MLU was performed with the mouse. Now it seems to work fine plus the Label now updates correctly which it didn't before.

Option Strict On

Imports System.Runtime.InteropServices

Public Class Form1

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _
    Private Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As Integer) As IntPtr
    End Function

    Private Const WM_LBUTTONDOWN = &H201
    Private Const WM_LBUTTONUP = &H202

    WithEvents MultiVarAnalysis As New DataTable("SixSigma")
    WithEvents MVASS As New BindingSource

    Dim DGVVScroll As New List(Of VScrollBar)
    Dim DGVHScroll As New List(Of HScrollBar)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
        Label1.Text = "Waiting"

        DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
        DataGridView1.Anchor = CType(AnchorStyles.Bottom + AnchorStyles.Left + AnchorStyles.Right + AnchorStyles.Top, AnchorStyles)
        DataGridView1.MultiSelect = False
        DataGridView1.AllowDrop = True
        DataGridView1.AutoSize = True
        DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.ColumnHeader

        MultiVarAnalysis.Columns.Add("Shift", GetType(String))
        MultiVarAnalysis.Columns("Shift").AllowDBNull = False
        MultiVarAnalysis.Columns.Add("Hello this is a long column", GetType(String))
        MultiVarAnalysis.Columns("Hello this is a long column").AllowDBNull = False
        MultiVarAnalysis.Columns.Add("Hour", GetType(String))
        MultiVarAnalysis.Columns("Hour").AllowDBNull = False
        MultiVarAnalysis.Columns.Add("Unit", GetType(String))
        MultiVarAnalysis.Columns("Unit").AllowDBNull = False
        MultiVarAnalysis.Columns.Add("Output", GetType(Double))
        MultiVarAnalysis.Columns("Output").AllowDBNull = False


        ' Add rows to DataTable

        MultiVarAnalysis.Rows.Add("A", "T1", "1st", "U1", 0.947)
        MultiVarAnalysis.Rows.Add("A", "T1", "1st", "U2", 5.427)
        MultiVarAnalysis.Rows.Add("A", "T1", "1st", "U3", 8.334)
        MultiVarAnalysis.Rows.Add("A", "T1", "1st", "U4", 4.637)

        MultiVarAnalysis.Rows.Add("A", "T1", "2nd", "U1", 4.766)
        MultiVarAnalysis.Rows.Add("A", "T1", "2nd", "U2", 4.461)
        MultiVarAnalysis.Rows.Add("A", "T1", "2nd", "U3", 5.791)
        MultiVarAnalysis.Rows.Add("A", "T1", "2nd", "U4", 2.313)

        MultiVarAnalysis.Rows.Add("A", "T2", "1st", "U1", 4.804)
        MultiVarAnalysis.Rows.Add("A", "T2", "1st", "U2", 5.238)
        MultiVarAnalysis.Rows.Add("A", "T2", "1st", "U3", 5.767)
        MultiVarAnalysis.Rows.Add("A", "T2", "1st", "U4", 5.108)

        MultiVarAnalysis.Rows.Add("A", "T2", "2nd", "U1", 3.829)
        MultiVarAnalysis.Rows.Add("A", "T2", "2nd", "U2", 5.539)
        MultiVarAnalysis.Rows.Add("A", "T2", "2nd", "U3", 8.18)
        MultiVarAnalysis.Rows.Add("A", "T2", "2nd", "U4", 4.86)

        MultiVarAnalysis.Rows.Add("B", "T1", "1st", "U1", 3.339)
        MultiVarAnalysis.Rows.Add("B", "T1", "1st", "U2", 8.978)
        MultiVarAnalysis.Rows.Add("B", "T1", "1st", "U3", 9.681)
        MultiVarAnalysis.Rows.Add("B", "T1", "1st", "U4", 3.86)

        MultiVarAnalysis.Rows.Add("B", "T1", "2nd", "U1", 2.816)
        MultiVarAnalysis.Rows.Add("B", "T1", "2nd", "U2", 5.519)
        MultiVarAnalysis.Rows.Add("B", "T1", "2nd", "U3", 7.321)
        MultiVarAnalysis.Rows.Add("B", "T1", "2nd", "U4", 4.321)

        MultiVarAnalysis.Rows.Add("B", "T2", "1st", "U1", 2.772)
        MultiVarAnalysis.Rows.Add("B", "T2", "1st", "U2", 7.431)
        MultiVarAnalysis.Rows.Add("B", "T2", "1st", "U3", 5.388)
        MultiVarAnalysis.Rows.Add("B", "T2", "1st", "U4", 6.911)

        MultiVarAnalysis.Rows.Add("B", "T2", "2nd", "U1", 3.5886)
        MultiVarAnalysis.Rows.Add("B", "T2", "2nd", "U2", 8.043)
        MultiVarAnalysis.Rows.Add("B", "T2", "2nd", "U3", 3.641)
        MultiVarAnalysis.Rows.Add("B", "T2", "2nd", "U4", 5.306)

        MultiVarAnalysis.Rows.Add("C", "T1", "1st", "U1", 3.929)
        MultiVarAnalysis.Rows.Add("C", "T1", "1st", "U2", 4.164)
        MultiVarAnalysis.Rows.Add("C", "T1", "1st", "U3", 8.427)
        MultiVarAnalysis.Rows.Add("C", "T1", "1st", "U4", 3.835)

        MultiVarAnalysis.Rows.Add("C", "T1", "2nd", "U1", 4.936)
        MultiVarAnalysis.Rows.Add("C", "T1", "2nd", "U2", 8.874)
        MultiVarAnalysis.Rows.Add("C", "T1", "2nd", "U3", 8.38)
        MultiVarAnalysis.Rows.Add("C", "T1", "2nd", "U4", 5.214)

        MultiVarAnalysis.Rows.Add("C", "T2", "1st", "U1", 4.059)
        MultiVarAnalysis.Rows.Add("C", "T2", "1st", "U2", 6.018)
        MultiVarAnalysis.Rows.Add("C", "T2", "1st", "U3", 4.035)
        MultiVarAnalysis.Rows.Add("C", "T2", "1st", "U4", 6.031)

        MultiVarAnalysis.Rows.Add("C", "T2", "2nd", "U1", 4.911)
        MultiVarAnalysis.Rows.Add("C", "T2", "2nd", "U2", 8.189)
        MultiVarAnalysis.Rows.Add("C", "T2", "2nd", "U3", 6.118)
        MultiVarAnalysis.Rows.Add("C", "T2", "2nd", "U4", 6.3)

        MultiVarAnalysis.Rows.Add("D", "T1", "1st", "U1", 2.834)
        MultiVarAnalysis.Rows.Add("D", "T1", "1st", "U2", 4.142)
        MultiVarAnalysis.Rows.Add("D", "T1", "1st", "U3", 12.935)
        MultiVarAnalysis.Rows.Add("D", "T1", "1st", "U4", 12.834)

        MultiVarAnalysis.Rows.Add("D", "T1", "2nd", "U1", 4.487)
        MultiVarAnalysis.Rows.Add("D", "T1", "2nd", "U2", 9.328)
        MultiVarAnalysis.Rows.Add("D", "T1", "2nd", "U3", 10.0245)
        MultiVarAnalysis.Rows.Add("D", "T1", "2nd", "U4", 6.387)

        MultiVarAnalysis.Rows.Add("D", "T2", "1st", "U1", 9.044)
        MultiVarAnalysis.Rows.Add("D", "T2", "1st", "U2", 6.322)
        MultiVarAnalysis.Rows.Add("D", "T2", "1st", "U3", 11.498)
        MultiVarAnalysis.Rows.Add("D", "T2", "1st", "U4", 7.943)
        MultiVarAnalysis.Rows.Add("D", "T2", "1st", "U5", 2.198)

        MultiVarAnalysis.Rows.Add("D", "T2", "2nd", "U1", 7.245)
        MultiVarAnalysis.Rows.Add("D", "T2", "2nd", "U2", 13.918)
        MultiVarAnalysis.Rows.Add("D", "T2", "2nd", "U3", 18.456)
        MultiVarAnalysis.Rows.Add("D", "T2", "2nd", "U4", 11.925)

        MultiVarAnalysis.AcceptChanges()
        MVASS.DataSource = MultiVarAnalysis
        DataGridView1.DataSource = MVASS

        For i = 0 To DataGridView1.ColumnCount - 1
            DataGridView1.Columns(i).SortMode = DataGridViewColumnSortMode.Automatic
        Next

        For Each Ctl As Control In DataGridView1.Controls.OfType(Of VScrollBar)()
            DGVVScroll.Add(CType(Ctl, VScrollBar))
        Next

        For Each Ctl As Control In DataGridView1.Controls.OfType(Of HScrollBar)()
            DGVHScroll.Add(CType(Ctl, HScrollBar))
        Next
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If DGVVScroll(0).Visible = True Then
            Label1.Text = "DataGridView1's VScrollBar is at " & DGVVScroll(0).Value.ToString & "."
        End If
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        If DGVVScroll(0).Visible = True Then
            DGVVScroll(0).Value = 40
            Dim p As New Point(DGVVScroll(0).ClientSize.Width - 5, DGVVScroll(0).Value - 5)
            Dim lparam As Integer = MakeLParam(p.X, p.Y)
            SendMessage(DGVVScroll(0).Handle, WM_LBUTTONDOWN, 0, lparam)
            SendMessage(DGVVScroll(0).Handle, WM_LBUTTONUP, 0, lparam)
            DataGridView1.Invalidate()
            Label1.Text = "DataGridView1's VScrollBar is at " & DGVVScroll(0).Value.ToString & "."
        End If
    End Sub

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        If DGVHScroll(0).Visible = True Then
            DGVHScroll(0).Value = 40
            Dim p As New Point(DGVHScroll(0).Value + 20, DGVHScroll(0).ClientSize.Height - 5)
            Dim lparam As Integer = MakeLParam(p.X, p.Y)
            SendMessage(DGVHScroll(0).Handle, WM_LBUTTONDOWN, 0, lparam)
            SendMessage(DGVHScroll(0).Handle, WM_LBUTTONUP, 0, lparam)
            DataGridView1.Invalidate()
            Label1.Text = "DataGridView1's HScrollBar is at " & DGVHScroll(0).Value.ToString & "."
        End If
    End Sub

    Public Function MakeLParam(LoWord As Integer, HiWord As Integer) As Integer
        Return ((HiWord << 16) Or (LoWord And &HFFFF))
    End Function

End Class



La vida loca

Mr. Monkeyboy on Tue, 17 May 2016 00:22:22


@halovalo

I just re-read your last post. And I tested and updated the code in my next to last post regarding using SendMessage and such. Now it should work with your DGV's HScrollBar. However depending on the width (length) of the HScrollBar slider or height (length) of the VScrollBar slider since for all I know they could end up being only 5 pixels wide (long) or high (long) the code could fail for setting the LParam in SendMessage.

Anyhow the DGV has both a VScrollBar and HScrollBar child control. So I altered the code to work with HScrollBar in Button3 click event. I also altered the code for working with the VScrollBar and added another List(Of HScrollBar) and code in Form Load to add the HScrollBar of the DGV to the list. I did not update the images to show Button3 or HScrollBar being displayed by DGV on the Form.

Regardless the code seems to work for either scroll bar if the DGV is displaying them which it will when necessary I suppose.


La vida loca

halovalo on Fri, 20 May 2016 13:04:17


Thanks for the exceptional answer. I will try to implement later on...

I did stumble upon a new problem.

My datagridview shows vertical scrollbar through entire DGV height. I'd like it to start from the top row and not the top of DGV.

Like VS should have its own header.

Any clues? Or should I consider to open a new thread instead...

Mr. Monkeyboy on Fri, 20 May 2016 14:38:22


Thanks for the exceptional answer. I will try to implement later on...

I did stumble upon a new problem.

My datagridview shows vertical scrollbar through entire DGV height. I'd like it to start from the top row and not the top of DGV.

Like VS should have its own header.

Any clues? Or should I consider to open a new thread instead...


I don't know what that means. You don't want to display column headers?

halovalo on Thu, 02 Jun 2016 06:17:18


No, I want to. I implemented the new panel with a new scrollbar as you suggested.

I placed it over an old embedded DGV scrollbar and placed another panel over the upper part of the old scroll bar (aligned with the headers section). I also placed a button in this upper panel..so I can do things with it later on. So all my problems from previous posts in this thread are GONE.

As I'm pushing forward my little project.... I noticed I will have to handle the mousescroll event in a way that scrollbar maxsize wont exceed when scrolling downwards. Now it shows error. Otherwise I managed to handle scrolling well. (no matter what is the recordcount it works well)

Mr. Monkeyboy on Thu, 02 Jun 2016 06:22:48


No, I want to. I implemented the new panel with a new scrollbar as you suggested.

I placed it over an old embedded DGV scrollbar and placed another panel over the upper part of the old scroll bar (aligned with the headers section). I also placed a button in this upper panel..so I can do things with it later on. So all my problems from previous posts in this thread are GONE.

As I'm pushing forward my little project.... I noticed I will have to handle the mousescroll event in a way that scrollbar maxsize wont exceed when scrolling downwards. Now it shows error. Otherwise I managed to handle scrolling well. (no matter what is the recordcount it works well)


I'm glad I could help you. Although whatever you are doing is beyond my understanding right now.

halovalo on Thu, 02 Jun 2016 06:42:39


I just corrected this issue...

I put a condition in mousewheel event and limited the wheel to the maximum. It works perfect now.

this is my final result for vertical scrollbar.


Thanks for your support.

Mr. Monkeyboy on Thu, 02 Jun 2016 06:50:54


Well that's nice. But your code is impossible to see and use.

La vida loca