需求:DataGridView通过绑定数据源方式实现定时更新、加载数据时,随着数据量的增加,该控件刷新显示的时间会随之增长,造成了界面卡顿,用户体验较差。
设计思路:查找多方资料后,决定使用DataGridView控件的虚拟模式来优化显示速度。
为何使用虚拟模式加载显示更快?
- 使用绑定数据源的方式,在定时更新获取表数据后,将数据全部加载到了DataGridView控件上,那么随着数据量越大,需要加载显示的时间也就越来越长;
- 使用虚拟模式方式,通过将数据源显示行数告知DataGridView控件,加载当前显示界面所看到的数据,并随着滚动条滚动对应刷新当前界面显示内容;
- 使用虚拟模式也并不是没有缺点,因为虚拟模式是一格一格取出来画出来的,所以需要不停地去数据源获取数据,或多或少都有些浪费资源。
实现如下:
第一步:在属性页面内,找到VirtualMode,赋值为True;也可以在后台界面加载时,使用“this.dgv_vote. VirtualMode=True;”方式修改。为了让读者更好理解,我尽量采用可视化方式解释。
第二步:告知DataGridView控件当前数据源显示总行数:this.dgv_vote.RowCount = ds_VoteSql.Tables[0].Rows.Count;
第三步:触发DataGridView的CellValueNeeded事件,根据自己的需要写显示逻辑
private void dgv_vote_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
if (ds_VoteSql.Tables[0].Rows.Count > e.RowIndex)
{
switch (e.ColumnIndex)
{
case 0: //第一列
e.Value = ds_VoteSql.Tables[0].Rows[e.RowIndex]["ID"].ToString();
break;
case 1: //第二列
e.Value = ds_VoteSql.Tables[0].Rows[e.RowIndex]["Name"].ToString();
break;
case 2: //第三列
e.Value = ds_VoteSql.Tables[0].Rows[e.RowIndex]["Num"].ToString();
break;
} else
{
return;
}
if (e.RowIndex == this.dgv_vote.RowCount)
{
return;
}
}
当写到这里,调试就可以看到数据已经加载出来,而且显示速度已经明显可以感觉出来了。对于不需要更新数据源的显示,已然足够;
第四步:定时更新数据源的处理;
使用异步委托的方式定时更新数据源,在这可能理解上面说的加载方式的会在获取最新要显示的数据后加载如下代码:
this.dgv_vote.RowCount = ds_VoteSql.Tables[0].Rows.Count;
this.dgv_vote.Refresh();
即重新告知控件更新显示总数量,并对控件进行刷新;
注意:此时有个问题,因为是虚拟加载,当数据变化是越来越多时,看不出来什么问题,而且还是很流畅;但是,当数据更新后的数量小于上次显示的数量时,程序就会卡住,打断点发现数值虽然变小了,可是程序在一格一格查找时仍然会去找之前多出来的那部分行数据;
多次试验后,采用如下方法解决卡顿:
this.dgv_vote.Rows.Clear();
this.dgv_vote.RowCount = ds_VoteSql.Tables[0].Rows.Count;
this.dgv_vote.Refresh();