winform_datagridview虚模式

背景:由于项目在UI中一次性加载的数据量有点大,导致后面的数据加载越来越慢。初始化的时候从数据库读取加载的数据也很多,这个过程耗时也很长。

思路:winform默认的表格采用“真绑定”的方式,对载入的数据都会进行全部识别并出个创建row和cell。采用虚模式显示,将数据和表分隔开,数据存在数据源中,表只是动态加载当前需要显示的数据内容。而且对于数据的维护也会更简单,只需要保证_data.Count = datagridview.RowCount;

实现:

  首先定义数据:

public readonly BindingList<TaskFile> _tabledata = new BindingList<TaskFile>();

  在datagridview的属性中,将VirtualMode改为true,并手动设置双缓冲为true(因为该属性为只读

FormLoad:{
     EnableDoubleBuffer(this.dgStudentInfo,true); 
}

 public static void EnableDoubleBuffer(DataGridView dgv, bool enable = true)
 {
     var pi = typeof(DataGridView)
              .GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
     pi?.SetValue(dgv, enable);
 }

  在构造函数或则界面加载中,给_data绑定一个事件,每次data改变的时候,同步到datagridview中

      _tabledata.ListChanged += (s, e) =>
      {
          // 统一用安全调用器回到 UI 线程
          SafeInvoke(this, () =>
          {
              this.datagridview.RowCount = _tabledata.Count;
              this.datagridview.Invalidate();            // 立即重绘
          });
      };

在需要改变数据的地方,直接对_tabledata进行增删改

 lock (_dataLock)
 {
     _tabledata.Add(curentTaskFile);
 }

最后就是在datagridview的事件中,写入自己的数据和cell绑定刷新的事件:

private void datagridview_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
    try
    {
        if (_tabledata == null || _tabledata.Count <= 0) return;
        if (e.RowIndex < 0 || e.RowIndex >= _tabledata.Count) return;   
        var row = _tabledata[e.RowIndex];
        if(this.datagridview.Rows[e.RowIndex].Tag == null)
            this.datagridview.Rows[e.RowIndex].Tag = row;

        string data = row.data;

        if (e.ColumnIndex == 0)
        {
            e.Value = EnumAnalyse.Normal;
        }
        if (e.ColumnIndex == 1)
            e.Value = e.RowIndex + 1;
        if (e.ColumnIndex == 2)
        {
            if (row.state != 0)
                e.Value = EnumHelper.GetDisplayAttributeName(typeof(ASheetExceptionType), row.aSheetExceptionType);
            else
                e.Value = row.stateRemark;
        }
        if (e.ColumnIndex == 3) 
        {
            if (row.isUpload == 1 && row.isCloudSync == 1)
                e.Value = "已上传";
            else
                e.Value = "待上传";
        }

        PaperInfoDto answerInfos = FileInfo(row);

        if(e.ColumnIndex == 4)
        {
            e.Value = row.Name;
        }
        if(e.ColumnIndex==5)
        {
            e.Value = answerInfos.Number;
        }
        if (data != "null" && data.Length > 0)
        {
            if (aInfos != null)
            {
                for (int j = 0; j < aInfos.datas.Count; j++)
                {
                    if (e.ColumnIndex >= 6)
                    { 
                        if(!string.IsNullOrEmpty(aInfos.datas[e.ColumnIndex - 6].Content))
                            e.Value = aInfos.datas[e.ColumnIndex - 6].Content;
                        else
                            e.Value = "-";
                    }
                }
            }
        }
        else
        {
            for (int j = 0; j < NumberAry.Length; j++)
            {
                if (e.ColumnIndex >= 6)
                    e.Value = "-";
            }
        }
    }
    catch (Exception ex)
    {
        Utils._log.Error($"CellValueNeeded 异常:RowIndex={e.RowIndex}, Count={_tabledata.Count}, {ex}");
    }
}

 

posted @ 2025-07-14 18:57  Wind_Swing_Dunn  阅读(45)  评论(0)    收藏  举报