我的应用程序中有一个表单显示一些数据。当我第一次显示表单时,我将一些数据加载到DataTable中,然后将DataTable绑定到DataGridView。我还启动了一个异步方法来执行一些较慢的数据库查询。当这些缓慢的查询完成时,我需要更新DataTable中的几百行,填充从缓慢查询返回的值,就像这样:
foreach (DataRow row in data.Rows)
{
SlowLoadingData slow_stuff = slow_query_results[(int)row["id"]];
row.BeginEdit();
row[column_one] = slow_stuff.One;
row[column_two] = slow_stuff.Two;
row[column_three] = slow_stuff.Three;
row.EndEdit();
}
这个操作非常慢,会导致UI线程挂起一分钟或更长时间,可能是因为每一行都触发了重绘。
经过一些研究,我找到了一种方法使其快速。首先,将DataGridView绑定到一个绑定到DataTable的BindingSource,而不是直接绑定到DataTable。然后,在对DataTable进行更改时,请按以下方式操作:
binding_source.SuspendBinding();
binding_source.RaiseListChangedEvents = false;
// foreach (DataRow in Data.Rows) ... code above
binding_source.RaiseListChangedEvents = true;
binding_source.ResumeBinding();
grid.Refresh();
不过存在一个大问题:上面的代码阻止了DataGridView检测添加到DataTable中的新行。 表格中不会显示任何新添加的行。 如果你使用箭头键将当前单元格选择移动到网格底部之外,那么网格也可能抛出异常,因为基础数据源有更多的行,但是网格没有创建用于显示它们的网格行。
所以,我能想到两个可能的解决方案:
是否有更好的方法来禁止绑定更新同时对基础DataTable进行更改?
是否有一种简单的方法可以告诉DataGridView优雅地刷新其网格行集合以匹配基础DataTable的行数? (注意:我尝试调用BindingSource.ResetBindings,但如果您从DataTable中删除行,则似乎会触发更多异常!)