我想要显示一张桌子。表的数据必须预先计算,并且计算量很大。结果表也很长。 我希望提供对部分数据的访问,而另一部分则在后台计算。
我编写后台工作程序进行计算,使用DataGridView进行显示。有时工作人员通过ProgressChangedEvent提交新行。我试图在底部添加这些行。 当我尝试在底部添加新行时,我的问题就出现了。我的用户界面冻结了。
以下是我初始化DataGridView的方法:
private void InitDataGridView()
{
BindingList<TableRow> tableRows = new BindingList<TableRow>();
dataGridView.DataSource = tableRows;
}
以下是我在ProgressChangedEvent
中添加新行的方法private void UpdateDataGridView (List<Items> newItems)
{
BindingList<TableRow> dataSource = (BindingList<TableRow>)this.dataGridView.DataSource;
foreach (var item in newItems)
dataSource.Add(new TableRow(item));
}
我认为这个问题是因为添加一行会重新开始重绘表格。 但我没有找到AddRange for BindingList或机制来暂停渲染。
有什么建议吗?
答案 0 :(得分:1)
通过向列表中添加新项目,BindingList
会引发ListChanged
,从而导致更新DataGridView
。为了提高DataGridView
的效率,您可以选择停止提升ListChanged
的{{1}}事件。这样,您可以在添加项目之前将其关闭,然后在将一组项目添加到列表后立即将其打开并引发事件。
这是一个支持启用/关闭BindingList
事件的实现:
ListChanged
例如,在添加项目时禁用该事件::
public class MyBindingList<T>:BindingList<T>
{
public bool EnableChangeNotifications { get; set; }
protected override void OnListChanged(ListChangedEventArgs e)
{
if(EnableChangeNotifications)
base.OnListChanged(e);
}
}
然后要显示list.EnableChangeNotifications = false;
//Add new items to the list using a loop or something else.
中的更改,请启用该事件并将其抬起:
DataGridView
答案 1 :(得分:0)
尝试将AutoSizeColumnsMode
属性设置为None
或DisplayedCells
,并在每列的AutoSizeMode
上设置:
foreach (DataGridViewColumn c in thisGrid.Columns)
{
c.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
}
尝试在绑定之前和之后以及更新时切换。
此外,您可以尝试在此answer上建议的内容并启用双缓冲:
if (!System.Windows.Forms.SystemInformation.TerminalServerSession)
{
Type dgvType = dataGridView1.GetType();
PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(dataGridView1, value, null);
}