随笔 - 0  文章 - 98  评论 - 1  阅读 - 52471

[转载]DataGridView的虚模式填充

系统中需要使用到了DataGridView控件来显示数据,采用了最简单和常用的逐行填充法,运行没问题,但是在大数据量的时候显示速度非常慢,考虑到系统使用场景中的数据量通常都在百万行以上,所以只能尝试使用虚模式(VirtualMode)来填充。
查看了MSDN里的资料,发现使用虚模式好像挺简单的,只要将DataGridView的VirtualMode属性设置为true,然后完成CellValueNeeded事件的处理代码就行。如果需要编辑数据的话,还需要自己处理CellValuePushed事件。

 

复制代码
代码
///<summary>
/// 创建列
///</summary>
void InitialGridViewData()
{
//创建编号列
DataGridViewColumn numcol =new DataGridViewTextBoxColumn();
numcol.Name
= NumberColName;
numcol.HeaderText
= NumberColName;
numcol.DefaultCellStyle.BackColor
= Color.FromArgb(212, 208, 200);
numcol.SortMode
= DataGridViewColumnSortMode.Programmatic;
numcol.ReadOnly
=true;
numcol.Tag
=false;
dataGridView.Columns.Add(numcol);

soFieldInfos osmFieldInfos
= oRst.GetFieldInfos();
for (int i =1; i <= osmFieldInfos.Count; i++)
{
soFieldInfo osmField
= osmFieldInfos[i];
string columnTitle = osmField.Name;
if (!string.IsNullOrEmpty(osmField.Caption))
columnTitle
= osmField.Caption;
DataGridViewColumn col
=new DataGridViewTextBoxColumn();
col.Name
= osmField.Name;
col.HeaderText
= columnTitle;
dataGridView.Columns.Add(col);
}
suSuperMap.ReleaseSmComObject(osmFieldInfos);
osmFieldInfos
=null;

//采用虚模式来填充数据
dataGridView.VirtualMode =true;
dataGridView.RowCount
= oRst.RecordCount +1;
}
复制代码

 

 

复制代码
代码
//单元格填充数据事件
void dataGridView_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
// If this is the row for new records, no values are needed.
if (e.RowIndex ==this.dataGridView.RowCount)
return;
// 从记录集中读取数据
string colName =this.dataGridView.Columns[e.ColumnIndex].Name;
if (colName.Equals(NumberColName))
{
e.Value
= e.RowIndex +1;
}
else
{
oRst.MoveTo(e.RowIndex
+1);
e.Value
= oRst.GetFieldValueText(colName);
}
}
复制代码

 

编译运行之后,果然显示速度非常快,用户根本无法察觉它的填充时间,这是因为虚模式只填充当前窗口中需要显示的那一小部分数据,实时根据滚动条位置刷新数据,并不是像逐条填充和数据源绑定时一次性将数据填充完成再显示,速度差距自然不能同日而语。

但发现有个问题:数据列表的最后一行空行一直在显示。这一行是控件本身提供的新增编辑行,便于用户增加新数据。但我系统中只用来编辑数据,并不新增和删除数据,该怎么去掉呢?

首先想到的是设置成禁止用户追加新行: 

this.dataGridView.AllowUserToAddRows =false;

运行后没有效果,可能是因为虚模式所致。

然后想到将DataGridView的行数减少一行,只显示现有的数据行,不显示新增行。
将dataGridView.RowCount = oRst.RecordCount + 1;修改成dataGridView.RowCount = oRst.RecordCount;
再次运行后发现,末尾的新增编辑行依然存在,而本来应显示的数据却少了一行。

 

从MSDN中找到关于这一行的说明,里面有关于末尾行的解释,说这一新增编辑行的在VirtualMode下无法控制,如果设置该行的Visible属性为false,还会引发不支持的操作异常。带着试试看的心态,决定试一试,于是修改单元格数据的填充事件:

 

复制代码
// If this is the row for new records, no values are needed.
if (e.RowIndex >=this.dataGridView.RowCount -1)
{
this.dataGridView.Rows[e.RowIndex].Visible =false;
return;
}
复制代码

想不到,这一改居然就真的不显示了,而且操作上也没有出现MSDN上所说的异常,不禁大喜。

可没高兴多久,发现当要显示的数据源记录为0条时,即数据本身为空时,出现了MSDN所说的“不支持的操作”的异常,这才发现原来MSDN是不跟程序员开玩笑的:)。

于是只好加个判断,如果当前数据源本身就为空,则这一末尾行显示,否则就隐藏:

 

复制代码
代码
// If this is the row for new records, no values are needed.
if (e.RowIndex >=this.dataGridView.RowCount -1)
{
this.dataGridView.Rows[e.RowIndex].Visible = e.RowIndex ==0?true : false;
return;
}
复制代码

 

 

这下不会出异常了,但是数据源为空的时候,会显示一行孤零零的空白数据,还是觉得有些看不顺眼。

 

过了几天,突然想起,可不可以在设置控件的行数(RowCount)的地方再加个判断呢?

于是在设置行数的地方也加个判断:

 

//采用虚模式来填充数据
dataGridView.VirtualMode =true;
int recordCount = oRst.RecordCount;
dataGridView.RowCount
= recordCount ==0?0 : recordCount +1;

 

现在,终于不会出现恼人的末尾多一个空白行的情况了,系统运行也正常。但是心底还是有点儿不甘,有没有爽快和更合适的解决方法呢?

 

BTW,使用虚模式填充时,DataGridView的SortMode设置成自动排序模式Automatic无效,只能自己实现排序功能。而且由于虚模式是实时地填充数据,排序功能的实现其实是对数据源的排序。

posted on   Arrow.Lu  阅读(409)  评论(1编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示