【问题标题】:C# WinForms DataGridView background color rendering too slowC# WinForms DataGridView 背景颜色渲染太慢
【发布时间】:2009-10-27 11:00:07
【问题描述】:

我正在像这样在 DataGridView 中绘制我的行:

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;
            }
        }        
    }

然后我在 OnLoad 方法中调用它:

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

            AdjustColors();           
        } 

我更喜欢 OnLoad 而不是 OnPaint 之类的......因为 OnPaint 经常被调用。

问题:为什么改变每一行的背景大约需要 100 - 200 毫秒? 早期,我在使用 CellPaint.. 但是在刷新滚动时遇到问题..

【问题讨论】:

  • 您的意思是每行需要 100 - 200 毫秒?听起来很沉重。
  • 多少行?您是否在表单上设置了双缓冲?您是否尝试过使用 CellFormatting 事件?

标签: c# winforms datagridview


【解决方案1】:

您应该让它通过覆盖CellFormatting 事件来管理渲染,而不是一次更改整个DataGrid 的颜色。只有在实际显示在屏幕上时才会绘制行。

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;
  }
}

如果这仍然太慢,请尝试获取该行绑定到的真实对象:

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

【讨论】:

  • 这可能是我无法自己处理绘画的证据,但我应该依靠MS提供的机制。现在所有行都立即重新着色!
  • 我按照 ShDevMan 的建议删除了 Enum.Parsing
  • +1 谢谢...我总是忘记在哪个事件中执行此操作。这将对每个单元格运行正确吗?我希望有一个事件每行只触发一次?
  • 如果要更改单个单元格的颜色,则测试引发事件的单元格:if (e.ColumnIndex == piecePartMasterGridview.Columns["AufgabeStatus"].Index)
【解决方案2】:

它可能是 Enum.Parse 调用,它的性能很差。您应该尝试将其更改为字典查找,以查看是否可以提高性能。看到这个post

【讨论】:

  • 你是对的,Enum.Parse 足够慢。我宁愿直接访问 DataBoundItem。
【解决方案3】:

正如 SwDevMan1 所说,您应该首先删除 Enum.Parse 调用。您是否使用数据绑定来填充网格?如果是这样,您可以使用 Rows[index].DataBoundItem 访问该行的数据绑定对象并直接访问 AufgabeStatus 状态。

我建议的第二个调整是在操作网格之前和之后分别调用 SuspendLayout() 和 ResumeLayout()。

【讨论】:

  • 我删除了 Parse 调用。是的,我正在使用 DataBounding。我直接通过 DataBoundItem 访问了元素。我试过暂停和恢复。它更快.. 但是 15 行仍然在大约 400 毫秒内着色..
【解决方案4】:

最好只设置与预期值不同的属性。这样您就不会触发不必要的内部 DataGridView 开销。

如果一行中的所有单元格都以相同的方式格式化,您可以在行级别而不是单元格级别进行格式化。

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

【讨论】:

    【解决方案5】:

    不要尝试行格式 作为 row.defaultcellstyle

    尝试单个单元格格式 ufgabenDataGridView_CellFormatting

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-29
      • 2014-05-27
      • 2020-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-19
      相关资源
      最近更新 更多