Windows Develop Bookmark and Share   
 index > Windows Forms General > DataGridView scrollbar corruption/bug
 

DataGridView scrollbar corruption/bug

I am seeing odd behavior with a DataGridView control, see the scenario description below. I think it is a bug, and I see that many other people have had the problem but a fix has not been issued. I also cannot seem to find a reasonable explanation of the problem or a workaround.

Scenario: DataGridView refreshes on a timer. If the grid refreshes while scrollbar arrow (down or right arrow) is clicked and held with the mouse, the scrollbar is 'corrupted'. By corrupt I mean that:
  1. The scrollbar arrow disappears, and the scrollbar no longer works for that direction (vertical or horizontal).
  2. Clicking the area where the arrow used to be and dragging allows the grid to be resized.
  3. Double-clicking the area where the arrow used to be maximizes the grid within the form as if it were an MDI child window.
  4. Once maximized, there is no way to restore the data grid to its original size.
I know that the problem only happens because the scrollbar(s) are being hidden and redisplayed during the refresh, effectively pulling the rug out from under my mouse click/hold. I know this because the problem does not happen with the horizontal scrollbar if the columns are static and only the rows are cleared/added.

I strongly feel that this is a bug because the problem does not happen when I click and drag the scrollbar itself, only when I click and hold the scrollbar arrow. In fact, it looks like the scrollbar handle is specifically coded to avoid this problem; if I click and drag the scrollbar during a refresh, my mouse click is 'cancelled' and is no longer dragging the scrollbar afterward.

The behavior is easily reproducable as follows:
  1. Create a test C# Windows Application (instructions and code below).
  2. Run the application. Click and hold the down arrow on the vertical scrollbar. (This also works for the right arrow on the horizontal scrollbar).
  3. When the timer event reloads the grid, the scollbar will break.

  • Create a new C# Windows Application named DataGridTest.
  • Increase the size of Form1, anything should work (I used 800x600).
  • Add a DataGridView control, make it smaller than the size of Form1 (I used 400x300).
  • Define a private timer variable within the Form1 class:
private System.Windows.Forms.Timer m_RefreshTimer;

  • Create an event handler for the form Load event. Add the following code to the event handler to initialize and start the timer:
private void Form1_Load(object sender, EventArgs e)
{
// Fill the grid once on load
RefreshTimer_Tick(null, null);

// Start the refresh time
m_RefreshTimer = new Timer();
m_RefreshTimer.Interval = 3000;
m_RefreshTimer.Tick += new EventHandler(RefreshTimer_Tick);
m_RefreshTimer.Start();
}

  • Create the timer event handler function as follows:
void RefreshTimer_Tick(object sender, EventArgs e)
{
dataGridView1.Rows.Clear();
dataGridView1.Columns.Clear();

// Add columns
for (int i = 0; i < 5; i++)
{
dataGridView1.Columns.Add("Column" + i.ToString(), "Column" + i.ToString());
}

// Add data rows
for (int i = 0; i < 15; i++)
{
dataGridView1.Rows.Add();
dataGridView1.RowsIdea.Cells[0].Value = i.ToString() + "_1234567890";
}
}


Kristofer J. DeMuth  Tuesday, June 03, 2008 8:17 PM

As a workaround, how about only updating if the mouse button is not depressed?

Code Snippet
void RefreshTimer_Tick(object sender, EventArgs e)
{

if(MouseButtons == 0)
{
dataGridView1.Rows.Clear();
dataGridView1.Columns.Clear();


// Add columns
for (int i = 0; i < 5; i++)
{
dataGridView1.Columns.Add("Column" + i.ToString(), "Column" + i.ToString());
}


// Add data rows
for (int i = 0; i < 15; i++)
{
dataGridView1.Rows.Add();
dataGridView1.Rows.Cells[0].Value = i.ToString() + "_1234567890"}

}

}

}

JayStation3  Tuesday, June 03, 2008 8:56 PM
Thank you for your suggestion, but I have seen that workaround suggested on other posts. I don't think it is a reasonable workaround for my project; I am using the DataGridView to display important log/error information that should be displayed to the user as soon as possible.

Rather, any suggestions on how I might cancel the user's mouse click so I can update in (near) real time?
Kristofer J. DeMuth  Tuesday, June 03, 2008 9:16 PM

Your timer ticks every 3 seconds, right? That seems quite frequent, like it might present performance issues, but that said, is a delay of 3 seconds going to make or break anything if the user happens to be scrolling? I don't think you want to cancel the user's scroll, because that means that at most, the user could only ever scroll for 3 seconds. Often the user would try to scroll and after only 1/2 second or 1 second, the action would stop inexplicably (from the user's perspective). If there is a lot of data to be viewed, the user may need to scroll considerably longer than that to find that for which they are looking. Canceling a scroll every 3 seconds could prove very frustrating to the user.

One alternative is to start a new, shorter timer if the update routine attempts to execute but a mouse button is depressed. Every time that timer ticks (say, every 1/2 second), it checks the mouse buttons, and if there are none depressed, it calls the update routine (and stops the short timer). That way the dgv gets updated when the user is done scrolling (and then continues on with the next tick of the 3-second timer).

JayStation3  Wednesday, June 04, 2008 4:03 PM
Thanks again for your response, JayStation3. The timer in the sample is just for simplicity to reproducing the problem. My production code updates the data grid when a message is received at an indeterminate time. This problem actually happened when a user was attempting to scroll when a message was received, thus updating the grid and corrupting the scrollbar.

I can't just update after the user releases the mouse as the data grid is not bound to a database; rows are added on the fly when a message is received. So if I don't update when the message is received, the data is lost.

I will probably end up either changing to another control, or buffering the data in memory then repopulating the grid based on the pseudocode below, unless Microsoft fixes the problem or someone suggests another alternative.



Kristofer J. DeMuth  Wednesday, June 04, 2008 5:43 PM

I think holding the data until the scroll arrow is released isa good solution.

You can create new rows as messages come in, and either add them directly to the dgv or, if the user is scrolling, hold them in a collection of rows until the user releases, at which time the row(s) in that collection get added at once as a range.

JayStation3  Wednesday, June 04, 2008 5:57 PM
A quick update on this issue:

I am working with a Microsoft Support Engineer, who is able to reproduce the issue on Windows XP (but not on Vista). He is investigating further. I will post more information as things progress.

Best regards,

Kris

Kristofer J. DeMuth  Monday, June 09, 2008 1:42 PM
Our customer is also very interested in a solution for this issue, so is there any update on this one.

thanks,
Christoph
Christoph Wagner  Tuesday, July 01, 2008 10:47 AM
Sorry I haven't been able to update this lately, been quite busy. I am still working with Microsoft, and if there is enough justification in terms of potential lost revenue, etc. then Microsoft can justify spending the time/$ to fix/test/release a patch. I will write a brief justification today, and let everyone know when I hear something back.

Kristofer J. DeMuth  Tuesday, July 01, 2008 3:11 PM

Hi,

I dont know if you solved your problem or not, but I was having the same issue with the scroll bars, it really stroke me out the first time i saw it, it only took a breakpoint in the scroll event to cause it, no timer, no adding removing rows, no nothing...

I tried many things, I was even about toimplement my own scroll bars when I realized the Layout events:

The Layout event occurs when child controls are added or removed, when the bounds of the control changes, and when other changes occur that can affect the layout of the control. The layout event can be suppressed using the SuspendLayout and ResumeLayout methods. Suspending layout enables you to perform multiple actions on a control without having to perform a layout for each change. For example, if you resize and move a control, each operation would raise a Layout event.

I believe this is what's happening:

During some event handling, the scroll control may enter a fragile state, in an indeterminate state.

If during that state the scroll control is disturbed once again, it could break causing the behaviour you described.

So try suspending the layout at the beginning of the event and resuming it before leaving and see if that solves your problem.

Let me know if this helps, I havent seen the "bug" since I applied this tweak. If you confirm it, then i can be sure it was not just afalse answer.

Good luck

ThoughtHopper;  Friday, July 18, 2008 7:25 PM
Thanks for your suggestion, ThoughtHopper. I have tried this before while working with the Microsoft Developer Support, but tried it again just to be sure!

Microsoft has confirmed that this is an actual bug that has been fixed for Windows Vista, but they were not planning on fixing it for Windows XP. I am working with them to remedy the situation, which includes justifying to MS the costs and risks involved if the bug is not fixed.

I'll post here again when MS confirms that the bug is fixed.

Best regards,

Kris
Kristofer J. DeMuth  Monday, July 21, 2008 10:11 PM
You have a lot of people here very interested in the fix for this issue, we found this issue, reported it and never heard anything. (Mid 2006) In fact just now I am working through yet another instance of this issue...

Is there an issue number for this that we can follow so we can be notified when/if a fix is available?
dodald  Tuesday, July 22, 2008 1:47 PM

Hi, I have the same issue. I'm reloading DataGrid data with async method called from thread. Problem occures when user keeps pressed scroll down arrow (I don't have horizontal scrollbar) while reloading data.

I tried already:

-turning off scroll bar before reloading

- suspending layout

- waiting while mouse is released (hangs appl)

- and some others

Does maybe anyone already found a really good and efficient solution/workaround? This is very important for me to fix it quick.

Best Regards,

SdNcenter  Tuesday, July 29, 2008 11:06 AM
A quick update on the issue:

I have been working with Microsoft Support Engineer since early June, and an Escalation Engineer from Microsoft Developer Support - User Interface group for the past few weeks. As of today, a hotfix request has been submitted to the Product group.

I am told that it "may take a few weeks to know if this problem can be fixed or not". The source of the problem is known and documented; I think what the engineer meant to say is "... if the problem *will* be fixed or not" as Microsoft may decide that this bug is not important, which it has thus far.

I will post more information as I receive it.

Best regards,

Kris
Kristofer J. DeMuth  Thursday, August 14, 2008 6:00 PM

It's a shame it's a bug.

While looking for a solution to my problem, this is the only place i found a description that resembled the problem i was having and the code you posted is very specific (using a timer).

Kristofer, you say the source of the problem is know and documented, may I know where or how this is?

Thanks

ThoughtHopper;  Thursday, August 14, 2008 6:10 PM

ThoughtHopper,

I meant that the problem is documented within Microsoft. I don't recall for sure how long ago it was reported, but I think the first Support Engineer indicated that the problem was reported in mid-late 2006; I don't recall for sure, but at least a year ago I think. The engineers I have spoken to since then deny this, and indicate that the problem is a slightly different one. In any case, I am told the problem is in ComCtl32.dll version 6, which supports Windows XP themes.

Also, the code I posted was just an example to help MS reproduce the problem, which they could not when I first contacted them. The problem can occur any time the scrollbar is being dragged/scrolled when the data refreshes. Clearing the data and columns should cause the control to send a Windows message to cancel the scrollbar event prior to removing the scrollbars, but this does not occur when visual styles are enabled for the application. This corrupts the control, and when the scrollbars are displayed again they are displayed incorrectly.

The problem is with support for visual styles; one of the early workarounds suggested to me was to disable visual styles for the application by removing commenting out the following line of code from Main() in Program.cs:

Application.EnableVisualStyles();


Removing the above line of code disables visual styles for the application. This will get around the problem, but the app will look like it is running on a resurrected Window 9X machine. Try it and see if it is acceptable to you; our customer is very particular.


Best regards,


Kris

Kristofer J. DeMuth  Friday, August 15, 2008 1:45 PM

I'm not super-familiar with VisualStyles/WindowThemes, but I have in the past used the SetWindowTheme function from the uxtheme.dll library to override the XP-style ProgressBar, without sacrificing the style of the rest of my form.

I have no idea if something like this could work on the scrollbars, but if you can figure out the handle to the controls, you could give it a shot.

(VB)

Code Snippet

Private Declare Unicode Function SetWindowTheme Lib "uxtheme.dll" _

(ByVal hwnd As IntPtr, _

Optional ByVal a As String = "", _

Optional ByVal b As String = "") _

As Integer

Once you have the handle(s), just pass each as the sole argument of a call to SetWindowTheme.

JayStation3  Friday, August 15, 2008 2:03 PM

Hi all,

my application also have similar problem. That is come from the XP style Vertical Scroll Bar.My application is written by VB 6 and runningunder Windows Server 2003 (SP2) with XP style enabled.

The application is a picture viewer. When press the down arrow, it will load a large amount of picture at the same time and this will casue the scroll bar corrupt.

The scroll bar become not accessable, try to access it will casue unexpected behaviour such as deform of Windows and Windows appearat random position.

After minimize and maximize it again, the scroll bar completely disappeared with transpartent effect.

It does not have any problem if XP style completely disabled.

I had tried to disabled the XP style for Vertical Scroll Bar alone, but it give me the same result.

It seems that it may cause memory flaw or security risk. I don't know M$ why not to fix this.

Please see the screen shot for the bug from the following links:

Start Loading Picture:

http://hk.geocities.com/fungko//StartLoading.jpg

Arrow disappeared after more pics are loaded.

http://hk.geocities.com/fungko/ArrowDisappeared.jpg

Windows Resize / deformed unexpecly when slide the scroll bar:

http://hk.geocities.com/fungko/UnexpectedBehaviour.jpg

Scroll bar completely disappeared and window become transparent after a redraw:

http://hk.geocities.com/fungko/RedrawIncorrectly.jpg

Working without problem if XP style completely disabled by delete the application.exe.manifest file.

http://hk.geocities.com/fungko/NoVisualStyle.jpg

Still have problem if disable XP style on Scroll Bar alone:

http://hk.geocities.com/fungko/ArrowDisappeared2.jpg

fungko  Sunday, September 21, 2008 9:04 AM

My application was had the exact same problem. Because the app is real time in nature, grid refreshes happen quite frequently, and are typically not initiated by the user. Also, for this particular app, EnableVisualStyles must be set to true.

The solution I employed was store the Date/Time that a grid was last scrolled, and to disable updating a grid if it has been scrolled within a second ago. I did some quick testing, and it looks like the scroll events fires anywhere from 50 to 200 ms apart during an active scroll session. So, 1 second is large enough to ensure a grid won't be refreshed during a scroll session, but short enough to ensure that the grid can update again almost immediately after they finish scrolling.

//...section of code that remembers the last scroll date/time

grid.Scroll += delegate( object sender, ScrollEventArgs e )

{

grid.Tag = DateTime.Now;

};

//...section of code that prevents refreshing a grid is the last scroll time was within a second ago

public void RefreshGrid( DataGridView grid ){

Debug.Assert( grid != null );

if( grid.Tag != null &&

DateTime.Now.Subtract( ( DateTime )grid.Tag ).TotalSeconds < 1 )

{

return;

}

//refresh the grid

}

Joel Lipschultz  Tuesday, October 14, 2008 5:59 PM

HiKristofer,

Do you have any news from Microsoft about this issue ?

Is there any patch from Microsoft ?

Thanks.

Regards.

Antonio.

AntoDC  Thursday, November 27, 2008 7:26 AM

To Microsoft,

We have just converted our application from Visual Basic 6.0 to Visual Basic 2005. Prior to the switch, we had a number of people out side out development team that wanted us to convert to the Linux environment. We use the DataGridView all over our application. We have a DataGridView that is updated at least once a minute based on events that are generated, but it can be updated more often. If you double click on the vertical down button or the horizontal right button, we get simular results as documented in previous posts. However, we have another form with a DataGridView control that is only updated when the form is loaded. After that, we have one column that the user can double click on to update that cell of the grid. I have noticed that, sometimes, if I double click on the vertical down button of the grid, the grid will maximize and fill the entire form. At this point, you can click on the lower left area of the grid and resize it. Resizing the form will cause it to return to its normal size (this is because we have code that resizes the grid if the user resizes the form), but it isn't in its original position (because we didn't expect its location to change).

This is a government application and the government is going to be using Windows XP for many years to come (whether Microsoft likes it or not). So waiting for Vista, is unexceptable. With the state of the government right now, do we really want the government to spend millions of the tax payers' money to convert everyone to Vista? That would be great for Microsoft, but not good for the nation. This problem needs to be fixed for XP. Now I understand why there is such a push by developers to switch from Microsoft Windows to Linux. If this was a Linux app., we wouldnothave to depend on Microsoft to get around to fixing it.

So, Microsoft, please fix this problem for Windows XP.

John Schlotter  Tuesday, December 02, 2008 7:03 PM
Hi All,

Can you guys please share the official tracking issue number from Microsoft for this?

Thanks.

Regards,
KH
EMGwave  Monday, September 14, 2009 9:48 AM
I've found this: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=115398

Can anyone verify is it the correct bug reporting that we are looking for?

Thanks.
EMGwave  Tuesday, September 15, 2009 9:40 AM

You can use google to search for other answers

Custom Search

More Threads

• how to disable the key combinations
• Chage Image Shapes
• Removing a tab page
• printing
• Menu links to utility programs howto?
• Display last of multiline tesbox.
• How to improve AutoComplete?
• DrawImage problem
• Resources.resx
• find checkbox value of datagridview in windows application