1

I have a DataGridView (DGV) that I'm populating manually (not bound to a datasource). It's relatively small (12 columns x 62 rows). When my form loads, it populates each cell with data from various sources, and applies style changes to some of the cells, such as fore color, background color, and possibly font change.

Everything is going great except for the style changes. I did some tests using Stopwatches, and the formatting is taking roughly 2X longer than all of the processing that goes into populating the form. My computations are fairly intensive, whereas I would think applying formatting would be almost instantaneous, so I'm baffled why applying some style changes is taking twice as long as my intense computations.

I've already taken some measures to reduce the time quite a bit, such as turning on double-buffering as well as suspending drawing for my DGV before my formatting begins and resuming it after. These helped a lot, and also eliminated the flicker that was happening as each cell of my DGV was repainted. As far as I can tell, doing these two things helped combine the actual painting of the style changes into a single paint operation. So a rough outline of the loading of my form goes like this:

  1. Form load begin
  2. "SuspendDrawing" for DGV
  3. Populate DGV with data
  4. Apply style changes to each cell
  5. "ResumeDrawing" for DGV and Refresh (Redraw) DGV.

To clarify, Step 4 is made up only of lines like the following:

myCell.Style = New DataGridViewStyle()
myCell.Style.BackColor = ...
myCell.Style.ForeColor = ...
myCell.Style.Font = New Font()

In all those steps, it's Step 4 that takes the most time. Even Step 5 is nearly instantaneous. This doesn't make sense to me. Drawing is suspended when Step 4 takes place, so there should be no graphics computations or painting taking place. It should purely be storing those Style changes for each cell.

So, why is applying cell style changes so slow, and what can I do to speed it up other than what I already have?

Update 2/5/20

I've been asked to provide reproducible code. I'll need to take some time to put together a MWE. In the meantime, hopefully this will help: after populating my table (step 3 above), I apply cell styles in Step 4 something like this:

For Each row As DataGridViewRow In myDGV.Rows
  For Each cell As DataGridViewCell In row.Cells
    Select Case [somecondition]
      Case X
        cell.Style = New DataGridViewStyle()
        cell.Style.BackColor = Colors.White
        cell.Style.ForeColor = Colors.Black
        cell.Style.Font = New Font(DefaultFont, FontStyle.Italic)
      Case Y
        [similar]
      Case ...
    End Select
  Next
Next
LarsTech
  • 80,625
  • 14
  • 153
  • 225
Sigenes
  • 445
  • 2
  • 13
  • You need to give us reproducible code. – LarsTech Feb 05 '20 at 22:01
  • *Where* /when are you applying these properties? It appears the you're not using the `CellFormatting`, `CellPainting` etc. events... So you're probably generating a whole lot of formatting events each time you change a single property. You could have provided an already configured object instead of changing each property of a *live* cell... – Jimi Feb 05 '20 at 22:03
  • I edited with some more details. If that's not enough, I'll put together a MWE tomorrow. – Sigenes Feb 05 '20 at 22:15
  • Use the provided events to format/paint the DGV's Cells/Rows. – Jimi Feb 05 '20 at 22:28
  • 2
    As suggested, you should be handling the appropriate events and configuring each cell on demand. That said, if you were going to do it your way, part of the problem is that you set the `Style` property of the cell first, then you set three properties of that `DataGridViewCellStyle`. That means that you are modifying a live cell four times. What you should be doing is creating and configuring the `DataGridViewCellStyle` first and then setting the `Style` of the cell. hat way, it's just one change. ALWAYS think about the order in which you do things related to the UI. – jmcilhinney Feb 06 '20 at 00:07
  • @jmcilhinney brilliant! As you suggested, I created and configured a Style variable for each iteration and assigned that to the cell, rather than modifying each live cell's style multiple times. This made the formatting time about 140X faster! It was about 1.4 seconds, now it's only 0.01 seconds. I may investigate using the `CellFormatting`/`CellPainitng` events in the future, but this will suffice for us for now. If you'll post that as an answer I'll accept it. – Sigenes Feb 06 '20 at 14:13
  • I'm happy for you to post your own answer based on your actual solution. – jmcilhinney Feb 07 '20 at 01:46

1 Answers1

1

I followed jmcilhinney's advice and created and configured a Style variable for each iteration and assigned that to the cell, rather than modifying each live cell's Style multiple times. This made the formatting about 140X faster, reducing it from 1.4 seconds to 0.01 seconds. My resulting code looked something like this:

For Each row As DataGridViewRow In myDGV.Rows
  For Each cell As DataGridViewCell In row.Cells
    Select Case [somecondition]
      Case X
        Dim styleVar as New DataGridViewStyle()
        styleVar.BackColor = Colors.White
        styleVar.ForeColor = Colors.Black
        styleVar.Font = New Font(DefaultFont, FontStyle.Italic)
        cell.Style = styleVar
      Case Y
        [similar]
      Case ...
    End Select
  Next
Next
Sigenes
  • 445
  • 2
  • 13