Windows Develop Bookmark and Share   
 index > Windows Forms General > DataGridView CellFormatting is very slow compared to custom painting -- why?
 

DataGridView CellFormatting is very slow compared to custom painting -- why?

Greetings,

I have a data-bound DGV. Each row has a different color background, foreground, etc. that can change as the underlying data changes. Originally, I handled the CellFormatting event, and changed the row Fore and Background colors accordingly, depending on the data in the underlying DataTable.

However, this proved to be incredibly slow at runtime. So then I decided to instead of handle the CellFormatting event, to handle the CellPainting event, where I determine (and then paint) the fore- and back-ground colors each time the rows needed painting. Oddly enough, this proved to be MUCH faster than the former approach.

However, now I'm starting to see an issue with the CellPainting approach. Namely, I now have an operation that takes a good bit of time (to determine what the appropriate background color should be for a particular row), but I should only have to perform this operation sparingly. However, because it exists in the CellPainting event, every time the row is painted, it must do this expensive operation.

So now I'm beginning to think I need to keep some Dictionary<DataGridViewRow, Color> where I can cache the background color for each row (when I need to, in other words do the "expensive" operation) and then in the CellPainting, I simply check to see if there is a cached Color for this particular row.

But what bothers me is the fact that I shouldn't have to do this!I should be able to handle the CellFormatting event, and then set the colors then, only when the cell's value is changed. However this is prohibitively slow!

So two questions, really:

1) why is handling the CellFormatting event so darn slow when compared to simply handling the CellPainting
2) how can I speed the CellFormatting event up (or is there another event altogether I should be using), so I don't have to manually manage which rows are "dirty" (and therefore I need to re-determine what background color they should have).

Thanks,
Rick
slikrik  Friday, September 11, 2009 4:13 PM
CellFormatting is called before every CellPainting call (except negative row/columns). Therefore, there will be no performance difference between one or the other.

Caching data that requires complex calculations is aperfectly acceptable solution. Use the data change event(s) on the data source to only do the recalcs when data changes.
  • Marked As Answer byslikrik Saturday, September 12, 2009 3:19 PM
  •  
Tergiver  Friday, September 11, 2009 8:35 PM
CellFormatting is called before every CellPainting call (except negative row/columns). Therefore, there will be no performance difference between one or the other.

Caching data that requires complex calculations is aperfectly acceptable solution. Use the data change event(s) on the data source to only do the recalcs when data changes.
  • Marked As Answer byslikrik Saturday, September 12, 2009 3:19 PM
  •  
Tergiver  Friday, September 11, 2009 8:35 PM
Odd.. I replied and this thread appears in My Threads, but I don't see my reply. Here it is again:

CellFormatting is called before every CellPainting event except on negative row/column indices (headers). That is why there is no performance difference between the two. If you observed one, you likely made a mistake somewhere, or changed something else as well.

Caching data that comes from long calculations is a perfectly acceptable solution. Use the data source's data change event(s) to update the cached values.
Tergiver  Friday, September 11, 2009 9:32 PM
Oh sure.. now I see my earlier reply. Weird.
Tergiver  Friday, September 11, 2009 9:34 PM
Thanks,

I have implemented the RowsChanged and RowsDeleting (RowsDeleted, unfortunately, throws exceptions if I try to access data from a deleted row... not sure what good this method is if you can't access the data).... and this seems to work well. Thanks for the advice.

Out of curiosity though, why does changing the Foreground and Background properties of the styles in CellFormatting give such worse performance than simply painting/drawing custom code in the CellPainting? It's as if setting .Foreground or .Background does some other series of method calls -- I just can't seem to figure it out.

Thanks again,
Rick
slikrik  Saturday, September 12, 2009 3:18 PM

Yes, you have to use RowDeleting rather than RowDeleted as the row is already gone (hense the past-tense verbage). You can use the same handler for both events and switch on e.Action if this helps reduce code duplication:

dataTable.RowDeleting += dataTable_RowChanged;
dataTable.RowChanged += dataTable_RowChanged; // Changed covers both Add and Change

void dataTable_RowChanged(object sender, DataRowChangeEventArgs e)
{
   switch (e.Action)
   {
       case DataRowAction.Add:
           break;
       case DataRowAction.Change:
           break;
       case DataRowAction.Delete:
           break;
   }
}

I don't know why you're seeing performance issues when setting those properties in CellFormatting. I've used the technique in many projects with no noticable problem. How many cells are visible (at maximum) in your application?

Tergiver  Saturday, September 12, 2009 3:32 PM
Hi Rick,

I see you are still having some problems with the beast! (DGV). Anyway I gave up trying to improve the performance of the DGV for about 3 months but it's come back to haunt me again! I put in another reply to the post I did way back in May, thought you might see it. Then I discovered this one. I also started another question under the title of

DataGridView performance issue

Whoa! that's big! Have a look if you like. It might be a possibility. I've spent the last few days working on it with very little sleep and it's the best I could come up with.
It relates the the problem you were having when untouched cells were being repainted. I believe this is one of the reasons the DGVs performance can degrade so much.
Especially if you have a large number of cells on your Grid(s)!

john.....
john1166  Wednesday, September 16, 2009 4:27 AM

You can use google to search for other answers

Custom Search

More Threads

• Close toolbar dropdownlist when mouse leaves
• GridSplitter hosted in a Grid in a windows forms does not work
• Little Drop Down menu
• Drag & Drop Question
• combobox abnormally fires events when scrollbar is used on .NET 1.1
• Help with text shifting logic.
• Custom AutoComplete filtering in ComboBox
• Displaying progress bar while loading data
• very urgent?Rich textbox in vb.net
• Can it be done in Whidbey? (Video streaming)