theSpyCry
theSpyCry

Reputation: 12283

C# WinForms DataGridView background color rendering too slow

I'm painting my rows in a DataGridView like this:

private void AdjustColors()
    {            
        foreach (DataGridViewRow row in aufgabenDataGridView.Rows)
        {
            AufgabeStatus status = (AufgabeStatus)Enum.Parse(typeof(AufgabeStatus), (string)row.Cells["StatusColumn"].Value);

            switch (status)
            {
                case (AufgabeStatus.NotStarted):
                    row.DefaultCellStyle.BackColor = Color.LightCyan;
                    break;
                case (AufgabeStatus.InProgress):
                    row.DefaultCellStyle.BackColor = Color.LemonChiffon;
                    break;
                case (AufgabeStatus.Completed):
                    row.DefaultCellStyle.BackColor = Color.PaleGreen;
                    break;
                case (AufgabeStatus.Deferred):
                    row.DefaultCellStyle.BackColor = Color.LightPink;
                    break;
                default:
                    row.DefaultCellStyle.BackColor = Color.White;
                    break;
            }
        }        
    }

Then I call it in the OnLoad method:

protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            AdjustColors();           
        } 

I prefer OnLoad to OnPaint or something.. because OnPaint is called very often.

The question: Why does it take about 100 - 200 ms to change the background of every row? Early, I was doint CellPaint.. but I had problems when scrolling with refreshing..

Upvotes: 12

Views: 8554

Answers (5)

Julien Poulin
Julien Poulin

Reputation: 13025

Instead of changing the color of the whole DataGrid at once, you should let it manage the rendering by overriding the CellFormatting event. The rows will only be painted when they are actually displayed on the screen.

private void aufgabenDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
  DataGridViewRow row = aufgabenDataGridView.Rows[e.RowIndex];
  AufgabeStatus status = (AufgabeStatus) Enum.Parse(typeof(AufgabeStatus), (string) row.Cells["StatusColumn"].Value);

  switch (status)
  {
    case (AufgabeStatus.NotStarted):
      e.CellStyle.BackColor = Color.LightCyan;
      break;
    case (AufgabeStatus.InProgress):
      e.CellStyle.BackColor = Color.LemonChiffon;
      break;
    case (AufgabeStatus.Completed):
      e.CellStyle.BackColor = Color.PaleGreen;
      break;
    case (AufgabeStatus.Deferred):
      e.CellStyle.BackColor = Color.LightPink;
      break;
    default:
      e.CellStyle.BackColor = Color.White;
      break;
  }
}

If this is still too slow, try getting the real object the row is bound to:

...
DataGridViewRow row = aufgabenDataGridView.Rows[e.RowIndex];
var aufgabe = (Aufgabe) row.DataBoundItem;
AufgabeStatus status = aufgabe.Status;
...

Upvotes: 17

sudhir goyal
sudhir goyal

Reputation: 1

don't try row format as row.defaultcellstyle

try individual cell formatting in ufgabenDataGridView_CellFormatting

cell[0].style.backcolor=color.yellow

Upvotes: 0

Olivier
Olivier

Reputation: 21

It's also a good idea to only set the properties if they differ from the expected value. That way you don't trigger unwanted internal DataGridView overhead.

If all cells in a row are formatted the same way, you can do the formatting on row level instead of cell level.

DataGridViewCellStyle rowStyle = row.DefaultCellStyle;
if (rowStyle.BackColor != status.BackColor) { 
   rowStyle.BackColor = status.BackColor;
}

Upvotes: 2

Jamie Ide
Jamie Ide

Reputation: 49261

As SwDevMan1 said, you should first work on removing the Enum.Parse call. Are you using data binding to populate the grid? If so, you can use Rows[index].DataBoundItem to access the data bound object for the row and access the AufgabeStatus status directly.

The second tweak I would suggest is to call SuspendLayout() and ResumeLayout() before and after, respectively, manipulating the grid.

Upvotes: 2

SwDevMan81
SwDevMan81

Reputation: 49988

Its probably the Enum.Parse call, it has poor performance. You should try and change it to a dictionary lookup to see if that improves performance. See this post

Upvotes: 2

Related Questions