DataGridView CellFormatting性能问题

本文关键字:问题 性能 CellFormatting DataGridView | 更新日期: 2023-09-27 18:05:48

如何修复CellFormatting "慢滚动"性能问题?

使用以下代码将解密值从加密列复制到另一列:

private void grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex < 0 || e.RowIndex < 0)
        return;
    var columnB = grid.Columns[e.ColumnIndex];
    if (columnB.Name != "B")
        return;
    var value = grid.Rows[e.RowIndex].Cells["A"].Value;
    if (value == null || value == DBNull.Value)
        return;
    e.Value = Decrypt(value.ToString());
}

DataGridView CellFormatting性能问题

如果性能问题是由于Decrypt方法,您应该避免在CellFormatting中使用它,如事件文档的备注部分所述:

每次绘制每个单元格时都会发生CellFormatting事件,因此在处理此事件时,应避免冗长的处理。

我可以使用什么解决方案来基于第一列为第二列提供值?

您可以使用以下两个选项之一:

  1. DataGridView添加第二列,并在for循环中提供值。
  2. 为数据源添加第二列(例如DataTable),并在for循环中提供值。

在下面的例子中,如果你从数据库中加载数据,它没有任何区别。但为了提供一个最小的完整可验证的示例,我自己创建了DataTable。在这两个示例中,LoadData方法加载一个DataTable:

private DataTable LoadData()
{
    var dt = new DataTable();
    dt.Columns.Add("ExistingColumn");
    dt.Rows.Add("x");
    dt.Rows.Add("y");
    dt.Rows.Add("z");
    return dt;
}

示例1 -为DataGridView添加列

var dt = LoadData();
dataGridView1.DataSource = dt;
//Add new column to DataGridView
var newColumn = new DataGridViewTextBoxColumn();
newColumn.HeaderText = "NewColumn";
newColumn.Name = "NewColumn";
dataGridView1.Columns.Add(newColumn);
//Copy Values
foreach (DataGridViewRow r in this.dataGridView1.Rows)
{
    if(!r.IsNewRow)
        r.Cells["NewColumn"].Value = Decrypt(r.Cells["ExistingColumn"].Value.ToString());
}

示例2 -在DataTable中添加列

var dt = LoadData();
dataGridView1.DataSource = dt;
//Add new column to DataTable
dt.Columns.Add("NewColumn");
//Copy Values
foreach (DataRow r in dt.Rows)
    r["NewColumn"] = Decrypt(r.Field<string>("ExistingColumn");

不要使用 CellFormating 方法。

我终于找到了一个很好的解决方案。

这是我的代码。

dgvTrucksMaster.SuspendLayout();
dgvTrucksMaster.DataSource = calendar.FailureCalendarDetails.OrderBy(x => x.MachineFullName).ToList();
foreach (DataGridViewRow row in dgvTrucksMaster.Rows)
{
    if (Convert.ToDouble(row.Cells["Decade1Hours"].Value) > 0)
    {
        row.Cells["Decade1Hours"].Style.BackColor = Color.LightGreen;
    }
    if (Convert.ToDouble(row.Cells["Decade1Hours"].Value) < 0)
    {
        // row.DefaultCellStyle.BackColor = Color.LightSalmon;
        row.Cells["Decade1Hours"].Style.BackColor = Color.LightSalmon;
    }
    if (Convert.ToDouble(row.Cells["Decade2Hours"].Value) > 0)
    {
        row.Cells["Decade2Hours"].Style.BackColor = Color.LightGreen;
    }
    if (Convert.ToDouble(row.Cells["Decade2Hours"].Value) < 0)
    {
        // row.DefaultCellStyle.BackColor = Color.LightSalmon;
        row.Cells["Decade2Hours"].Style.BackColor = Color.LightSalmon;
    }
    if (Convert.ToDouble(row.Cells["Decade3Hours"].Value) > 0)
    {
        row.Cells["Decade3Hours"].Style.BackColor = Color.LightGreen;
    }
    if (Convert.ToDouble(row.Cells["Decade3Hours"].Value) < 0)
    {
        // row.DefaultCellStyle.BackColor = Color.LightSalmon;
        row.Cells["Decade3Hours"].Style.BackColor = Color.LightSalmon;
    }
    if (Convert.ToDouble(row.Cells["DecadeMonthHours"].Value) > 0)
    {
        row.Cells["DecadeMonthHours"].Style.BackColor = Color.LightGreen;
    }
    if (Convert.ToDouble(row.Cells["DecadeMonthHours"].Value) < 0)
    {
        // row.DefaultCellStyle.BackColor = Color.LightSalmon;
        row.Cells["DecadeMonthHours"].Style.BackColor = Color.LightSalmon;
    }
    for (int i = 0; i < 61; i++)
    {
        if (Convert.ToDouble(row.Cells[string.Format("D{0}", i + 1)].Value) < 0)
        {
            row.Cells[string.Format("D{0}", i + 1)].Style.BackColor = Color.LightSalmon;
        }

        if (Convert.ToDouble(row.Cells[string.Format("D{0}", i + 1)].Value) > 0)
        {
            row.Cells[string.Format("D{0}", i + 1)].Style.BackColor = Color.LightGreen;
        }
    }
}
dgvTrucksMaster.ResumeLayout();

正如您从代码中看到的,关键是在应用Data Source之后和ResumeLayout方法之前更改CellFormating

试试吧,你会对结果满意的。

哦!并确保在 BeginInvoke((Action)(() => { // Some code }); 代码中执行此操作。所以请异步获取并准备Data Source