将样式更改应用于 DataGridView 中的各个单元格非常慢

问题描述 投票:0回答:2

我有一个手动填充的 DataGridView (DGV)(未绑定到数据源)。它相对较小(12 列 x 62 行)。当我的表单加载时,它会使用来自各种来源的数据填充每个单元格,并对某些单元格应用样式更改,例如前景色、背景色,可能还包括字体更改。

除了风格的改变之外,一切都很顺利。我使用秒表做了一些测试,格式化所花费的时间比填充表单的所有处理时间大约长 2 倍。我的计算相当密集,而我认为应用格式几乎是瞬时的,所以我很困惑为什么应用一些样式更改所花费的时间是我密集计算的两倍。

我已经采取了一些措施来大大减少时间,例如在格式化开始之前打开双缓冲以及为我的DGV暂停绘图,然后再恢复。这些很有帮助,并且还消除了重新绘制 DGV 的每个单元时发生的闪烁。据我所知,做这两件事有助于将风格变化的实际绘制结合到单个绘制操作中。所以我的表单加载的大致轮廓如下:

  1. 表单加载开始
  2. DGV 的“暂停绘图”
  3. 用数据填充 DGV
  4. 将样式更改应用到每个单元格
  5. DGV 的“ResumeDrawing”和刷新(重绘)DGV。

澄清一下,步骤 4 仅由如下行组成:

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

在所有这些步骤中,第 4 步花费的时间最多。甚至第 5 步也几乎是瞬间完成的。这对我来说没有意义。当步骤 4 发生时,绘图暂停,因此不应进行任何图形计算或绘画。它应该纯粹存储每个单元格的样式更改。

那么,为什么应用单元格样式更改如此缓慢,除了我已有的之外,我还能做些什么来加快速度?

更新2/5/20

我被要求提供可重现的代码。我需要花一些时间来整理 MWE。同时,希望这会有所帮助:填充我的表格(上面的步骤 3)后,我在步骤 4 中应用单元格样式,如下所示:

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
vb.net winforms performance datagridview
2个回答
1
投票

我遵循了 jmcilhinney 的建议,为每次迭代创建并配置了一个

Style
变量,并将其分配给单元格,而不是多次修改每个活动单元格的
Style
。这使得格式化速度提高了约 140 倍,从 1.4 秒减少到 0.01 秒。我生成的代码看起来像这样:

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

0
投票

拦截单元格的绘制事件可能会更有效。要强制单元格重新绘制,您可以使用 DataGridView.InvalidateCell(cell)

就像在此示例代码中一样,单元格样式单独存储在cells列表中,并且在通过外部代码更新后,将触发绘制事件以反映更改。

dataGridView.CellPainting += (sender, e) =>
{
    // Example: Check if this cell is one that should have a fading effect
    var cellFadeInfo = cells.Find(c => c.Cell.RowIndex == e.RowIndex && c.Cell.ColumnIndex == e.ColumnIndex);
    if (cellFadeInfo != null)
    {

        // Assume GetFadeColorForCell returns the appropriate color based on some custom logic
        Color fadeColor = cellFadeInfo.CurrentColor;
        if (fadeColor != null) using (Brush cellBackgroundBrush = new SolidBrush(fadeColor))
            {
                // Paint the cell background with the fade color
                e.Graphics.FillRectangle(cellBackgroundBrush, e.CellBounds);
                // Ensure text and other elements are painted over the background
                e.PaintContent(e.ClipBounds);
                e.Handled = true; // Indicate that the cell painting has been handled
            }
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.