WinForms DataGridView性能对比:循环遍历行VS行事件驱动计算
DataGridView两种非绑定列计算方式的性能差异原因
场景描述
在基于.NET Framework的WinForms应用中,有一个绑定到DataTable的DataGridView,包含3列。前两列绑定到DataTable的对应列,第三列为非绑定列,需基于前两列的值计算得出。
尝试了两种实现方式:
方式1:遍历DataGridView行计算
this.TABLE1TableAdapter.Fill(this.DataSet1.TABLE1); foreach (DataGridViewRow c in DataGridView1.Rows) { var r = c.DataBoundItem.row; c.Cells("column3").Value = string.Format("{0}/{1}", r.column1, r.column2); }
方式2:通过CellFormatting事件实时计算
private void DataGridView1_CellFormatting(DataGridView sender, DataGridViewCellFormattingEventArgs e) { if (e.ColumnIndex == 3) { DataSet1.TABLE1Row r = sender.Rows(e.RowIndex).DataBoundItem.row; e.Value = string.Format("{0}/{1}", r.column1, r.column2); } }
两种方法均能得到预期结果,但事件驱动方式仅耗时6秒,循环遍历方式却耗时60秒。原本以为循环方式性能更优,请问差异原因是什么?
原因分析
核心差异在于两种方式触发的UI和数据绑定开销完全不同:
遍历行设置Cell值的开销问题:
每一次给c.Cells("column3").Value赋值时,都会触发DataGridView的单元格值变更通知,进而引发UI重绘、绑定验证等一系列额外操作。如果数据量较大,每一行的操作都会累积大量重复的UI刷新和绑定逻辑执行,这是循环方式耗时的主要原因。而且DataGridView的行是UI控件对象,直接操作它们的本身开销就远高于后台数据操作。CellFormatting事件的优化机制:
这个事件是WinForms专门为控件显示优化设计的:- 仅在单元格即将被绘制到界面时触发(比如滚动到该行、窗口激活),当前不在可视区域的行不会触发事件,相当于只计算需要显示的内容;
- 事件中设置
e.Value是在绘制流程内完成,不会触发额外的数据绑定变更通知,也不会导致整个控件的频繁刷新,避免了不必要的性能消耗。
内容的提问来源于stack exchange,提问作者Vadim Rapp
相关产品推荐
相关产品推荐

