You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DataGridView批量更新数千单元格速度极慢问题求助

DataGridView批量更新性能优化方案

问题背景

我有一个约30000行、仅两列的DataGridView,仅允许编辑每行第一列单元格。用户编辑完该单元格后,需要将所有第一列值与原值匹配的行更新为新值,并给这些单元格应用黄色背景样式。

我在CellValueChanged事件中实现了逻辑,但操作数千行时耗时约10分钟。已尝试在循环前后暂停/恢复布局,无明显改善。所有行均为手动从列表添加,未使用数据绑定。

原实现代码:

private void SamplesTable_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (_isEditing)
    {
        return;
    }

    _isEditing = true; // 避免更新多个单元格时重复触发事件

    foreach (DataGridViewRow row in SensorsTable.Rows)
    {
        // 只修改和触发事件的旧值匹配的单元格
        if (!row.Cells[0].Value.ToString().Trim().Equals(_oldValue, StringComparison.OrdinalIgnoreCase))
        {
            continue;
        }

        row.Cells[0].Value = newValue;
        row.Cells[0].Style = cellStyle; // cellStyle是预先定义的DataGridViewCellStyle,背景色为黄色
    }

    _isEditing = false;
}

优化方案

1. 用字典映射减少遍历次数

既然是手动添加行,提前维护一个字典,键为第一列值的标准化格式(比如Trim后转小写),值为对应行的集合。这样编辑后直接通过字典找到匹配行,不用遍历全部3万行:

// 全局字典,存储值到行集合的映射
private Dictionary<string, List<DataGridViewRow>> _valueRowMap = new Dictionary<string, List<DataGridViewRow>>(StringComparer.OrdinalIgnoreCase);

// 添加行时同步更新字典
private void AddRowToGrid(DataGridViewRow row)
{
    string key = row.Cells[0].Value.ToString().Trim();
    if (!_valueRowMap.ContainsKey(key))
    {
        _valueRowMap[key] = new List<DataGridViewRow>();
    }
    _valueRowMap[key].Add(row);
    SensorsTable.Rows.Add(row);
}

2. 批量操作时禁用更多DataGridView更新机制

仅暂停布局不够,操作期间临时关闭不必要的UI更新逻辑:

private void SamplesTable_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    if (_isEditing) return;
    _isEditing = true;

    // 保存原有设置
    bool originalHeaderStyle = SensorsTable.EnableHeadersVisualStyles;
    bool originalRowHeaderVisible = SensorsTable.RowHeadersVisible;
    
    // 禁用不必要的UI更新
    SensorsTable.SuspendLayout();
    SensorsTable.ReadOnly = true;
    SensorsTable.EnableHeadersVisualStyles = false;
    SensorsTable.RowHeadersVisible = false;

    try
    {
        string oldKey = _oldValue.Trim();
        if (_valueRowMap.TryGetValue(oldKey, out var targetRows))
        {
            foreach (var row in targetRows)
            {
                row.Cells[0].Value = newValue;
                row.Cells[0].Style = _highlightStyle;
            }
            // 更新字典:移除旧键,把行添加到新键下
            _valueRowMap.Remove(oldKey);
            string newKey = newValue.ToString().Trim();
            if (!_valueRowMap.ContainsKey(newKey))
            {
                _valueRowMap[newKey] = new List<DataGridViewRow>();
            }
            _valueRowMap[newKey].AddRange(targetRows);
        }
    }
    finally
    {
        // 恢复原有设置
        SensorsTable.RowHeadersVisible = originalRowHeaderVisible;
        SensorsTable.EnableHeadersVisualStyles = originalHeaderStyle;
        SensorsTable.ReadOnly = false;
        SensorsTable.ResumeLayout();
    }

    _isEditing = false;
}

3. 复用CellStyle对象

把高亮样式设为全局静态变量,避免每次创建新对象:

// 全局复用的高亮样式
private static readonly DataGridViewCellStyle _highlightStyle = new DataGridViewCellStyle { BackColor = Color.Yellow };

4. 一次性刷新UI

如果允许,修改完所有单元格后调用SensorsTable.Refresh()一次性刷新,替代每个单元格单独触发的UI更新。

内容的提问来源于stack exchange,提问作者pfinferno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:12:42