Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > DataGridView performance issue
 

DataGridView performance issue

I have recently been doing a lot of work with the DGV control and found that its performance is severely degraded when a large amount of cells get repainted. I'm
only updating the grid about once every second sometimes twice a second and as it updates it sweeps across my 19" wide screen very noticeably. (Annoying!)
After a bit of experimentation and streamlining some code, I was only able to improve the DGVs performance only marginally. All formatting of the cells are done
in the CellPainting handler and cells are not modified directly. The data is not bound to the control as it freely comes in from the exchange and needs to be
decompressed before it is displayed.

What I've tried so far:
When the data comes in and is compared to the data from the previous response and a change has occurred, the individual cell is invalidated with
dgv.InvalidateCell(column, row). After inserting an integer counter into the CellPainting handler it revealed that even though invalidation was made at
the cell level, adjacent cells were being accessed/painted. As an example if 2 cells in the 1st column at row 2 and row 11 were invalidated, then the CellPainting
handler would be triggered 10 times as indicated by the integer counter inside the handler. Likewise if the 2nd cell was at row 11 and in the 2nd column,
you guessed it, the integer counter was incremented 20 times! This sounds like it could be a prediction feature of the DGV. It's as if you were to click a cell with
the left mouse button, hold and drag to another point. The 1st and last cell in the selection you made corresponds to the 2 cells that were originally invalidated
and as I discovered everything else in between!

If on the other hand only 1 cell was in invalidated, then only that cell would trigger the CellPainting handler. At worst if the only 2 cells to get invalidated were
the 1st and last in the grid, then the entire grid is repainted. The integer counter was placed after all the code that formatted the cell in the CellPainting handler.
I certainly hope this is clear on how I came to my conclusion.
Ok well, I've searched hi and lo and Googled till I couldn't Google no more! But I believe there might be one possibile solution and that is to call the CellPainting
event directly rather than have it triggered. Unfortunately the DataGridViewCellPaintingEventArgs are Non-public members of the DGV and I don't know how to
pass it when I call the CellPainting event manually. To test my theory I created 2 DataGridViewCellPaintingEventArgs global variables and initialized them inside
the CellPainting handler when the form loaded by passing them back and forth within the CellPainting handler. Then I pressed a button which called the CellPainting
handler twice in succession. Lo and behold and to my surprise, I got the number 2 from my integer counter!!!

My question is, how do I send as CellPaintingEventArgs the cell at (row, column) when I call the CellPainting method directly as I believe this will (should) work!
To a lot of you experienced programmers out there, this might sound like the wrong way of doing it, but I've run out of ideas and it appears that I would get the
performance I am after from the DGV. I do like the features of the DGV and I don't want to create a grid class of my own. I glanced at some articles talking
about Reflection, didn't really delve into it!

So if anyone can help, it would be much appreciated!

john.....
john1166  Wednesday, September 16, 2009 3:54 AM

Hi john1166,

Could you let me know why you need to handle the CellPainting event?

From my experience, The cell painting would not cause a low performance. The root causes of the low performance is mostly related to the row adding or editing. For example, when a DataGridView is shown, if lots of DataGridViewRows are added or the Values of a lot of DataGridViewCells are set, the performance would be very low since the DataGridView is refreshed too many times.

To improve the performance, we often bind a data source to a DataGridView. If we want to add lots of rows to it or lots of cells need to be modified, we can suspend the binding from data source to the DataGridView and do want we want in the data source, then resume the binding. The thread below shows how to do this in detail:
http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/d2102485-3223-4032-b397-2adb08e2d30a.

Let me know if this does not help.
Aland Li


Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread.
Aland Li  Thursday, September 17, 2009 9:13 AM
Hello Aland,

And thank you for taking the time to answer my question.

I guess I forgot to mention that one of the grids I'm currently working on has 20 columns and 55 rows (not including headers). The entire grid remains static in the sense that
I don't add any rows or columns and all formatting to the cells are done only when the CellPainting event is triggered. Below this grid I've placed a horizontal scroll bar which is
not part of the grid itself. I have data loaded in a list and I use the scrollbar to cycle through the data forwards and backwards. If a change in value is noticed then only that
cell is modified using dgv.InvalidateCell(column, row) and I use the CellPainting event exclusively to format how I want the results to display.

In my previous post I was merely giving a very simple example and explanation of how I produced those results.

May I suggest you use the code below to try it out for yourself. Just use the default names for the three components datagrid, button and label. Stretch the grid out so you
can see all of the 100 cells so you don't have to scroll. There is absolutely no need to bind any data to the grid or to place anything in the cells. To
demonstrate what I mean in my last post, click on a cell to highlight it. Now click on a different cell somewhere else on the grid. Do this a few times and you will understand
what I am trying to say. As you will see, the counter will change value a different number of times depending on where you click on the grid. It will show you exactly the
number of times the CellPainting event fires for something as trivial as changing the current cell! I hope the code posts all right. I haven't posted code before.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace dgvTester
{
public partial class Form1 : Form
{
private int counter = 0;

public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.RowCount = 10;
dataGridView1.ColumnCount = 10;
for (int column = 0; column < dataGridView1.ColumnCount; column++)
dataGridView1.Columns[column].Width = 50;
dataGridView1.CellPainting += new System.Windows.Forms.DataGridViewCellPaintingEventHandler(this.dataGridView1_CellPainting);
}

private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
counter++;
label1.Text = counter.ToString();
}

private void button1_Click(object sender, EventArgs e)
{
counter = 0;
label1.Text = counter.ToString();
}
}
}

I do believe that calling the CellPainting event directly will avoid unnecessary firing of this event on cells that remain static.
So is there a way to pass the CellPaintingEventArgs by calling the CellPainting event directly with the cell I want to modify?

I found this after a few days of Googling for an answer to my problem.

http://www.koders.com/csharp/fid1DBCB1E079D023FE239DE7F27C34FAC67DA643AF.aspx?s=cdef%3Adatagridview#L34

I don't know how to incorporate this into my project as I'm fairly new to Oop.

Waiting anxiously for a reply!

john...

john1166  Thursday, September 17, 2009 3:37 PM

You can use google to search for other answers

Custom Search

More Threads

• primary key issue on related tables
• Stop DataGridView from Resetting
• Auto detecting remote or local SQL Server
• [solved] DataGridView.Sort explodes after modifying/adding row(s)...
• binding datagridview to a bindingsource
• Can I access the DataTable_ColumnChanged Event..............
• Fill DataGridView ComboBox column?
• selecting more than one rows of datagrid in framework 1.1
• Database connection to SQL server through VB(Windows appliatioon VS 2005)
• ListView columns