更新数据源时刷新DataGridView

70
什么是在更新基础数据源时刷新DataGridView的最佳方法?
我经常更新数据源,并希望在发生更改时向用户显示结果。
我有类似以下的代码(它可以工作),但将 DataGridView.DataSource 设置为 null 似乎不是正确的方法。
List<ItemState> itemStates = new List<ItemState>();
dataGridView1.DataSource = itemStates;

for (int i = 0; i < 10; i++) { 
    itemStates.Add(new ItemState { Id = i.ToString() });
    dataGridView1.DataSource = null;
    dataGridView1.DataSource = itemStates;
    System.Threading.Thread.Sleep(500);
}

你能否看一下我的回答,如果它是最合适的,那就请接受它好吗? - Alexander Abakumov
8个回答

57
我自己也遇到了这个问题。我的建议是:如果您拥有数据源,请不要使用 List,而是使用BindingListBindingList具有在添加或更改项目时触发事件的功能,当这些事件被触发时,DataGridView会自动更新自己。

4
这是一个不错的建议。之后,您只需调用 .Refresh() 来刷新 datagridview 显示的数据即可。 - veljkoz
3
可以使用以下方式逐行刷新:bindingList.ResetItem(bindingList.IndexOf(item));。 - Adam Butler
4
.Refresh() 只涉及控件重绘,与绑定无关,除非我大错特错!"强制控件使其客户区域失效并立即重绘自身和任何子控件。"Control.Refresh 方法 - Paul C
1
使用BindingListBindingSource,并使用ResetBindings对我没有起作用。 - PeterX

50

这简直不能再好了。官方建议使用

dataGridView1.DataSource = typeof(List); 
dataGridView1.DataSource = itemStates;

这仍然是一种“清除/重置数据源”的解决方案,但我尚未找到其他可靠地刷新DGV数据源的方法。


1
使用typeof(List)而不是null的意义是什么? - GWLlosa
5
如果您正在使用自动生成的列,并将数据源设置为NULL,则会清除这些列。通过使用typeof(List),它应该在刷新期间保持列结构不变。我个人会使用AutoGenerateColumns = false;并在第一次刷新时创建列。这样,如果用户调整了某个列的大小,在刷新时它就不会丢失更改。 - Chris Porter
3
为什么不使用 BindingSource,这样你就可以轻松地刷新内容了。与重新绑定相比,这种方法更加干净、整洁。 - Paul C
1
@CodeBlend - 如果你指的是BindingSource.ResetBindings(),它对我来说并没有刷新项目。DataSource属性需要被“清除”并重新设置才能看到任何更改。如果有一个使用BindingSource的工作示例,那就太好了;) - Alan
1
仅将 dataGridView1.DataSource 设置为新数据的问题是什么?即使 AutoGenerateColumns 为真,这将自动更新网格而不会删除列的结构。 - S.Serpooshan
显示剩余6条评论

30

在这种情况下,最干净、高效和符合范例的解决方案是使用 System.Windows.Forms.BindingSource 作为您的项目列表(数据源)与 DataGridView 之间的代理:

var itemStates = new List<ItemState>();
var bindingSource1 = new System.Windows.Forms.BindingSource { DataSource = itemStates };
dataGridView1.DataSource = bindingSource1;

在添加项目时,使用BindingSourceAdd()方法而不是列表自己的Add()方法:

for (var i = 0; i < 10; i++)
{
    bindingSource1.Add(new ItemState { Id = i.ToString() });
    System.Threading.Thread.Sleep(500);
}

通过这种方式,您可以向列表添加项目,并使用同一行代码通知DataGridView有关这些添加的信息。每次更改列表时,无需重置DataGridViewDataSource

值得一提的是,在Visual Studio的表单设计器中可以直接放置BindingSource并将其附加为DataGridView的数据源,这样可以节省在上面的示例中手动执行的一行代码。


4
这个答案应该被标记为正确答案。我投票支持这个答案。 - jsa
@jsa:不幸的是,OP自2009年以来就没有再访问SO了。 - Alexander Abakumov
2
毫无疑问,这是最好的答案——可惜另一个回答获得了很多赞,但从日期来看它已经有更久的时间来收集它们! - Billious
1
好的解决方案,bindingsource[e.RowIndex]=mylist; 对我非常有效,而不是 datagridview.Refresh(); 谢谢 @Alexander。 - Sharif Lotfi

3

ObservableCollection:表示一种动态数据集合,当项目被添加、删除或整个列表被刷新时会提供通知。可以枚举实现IEnumerable接口的任何集合。 然而,为了设置动态绑定,以便插入或删除集合中的内容能自动更新UI,集合必须实现INotifyCollectionChanged接口。 该接口公开了CollectionChanged事件,应该在基础集合更改时引发该事件。

Observablecollection<ItemState> itemStates = new Observablecollection<ItemState>();

for (int i = 0; i < 10; i++) { 
    itemStates.Add(new ItemState { Id = i.ToString() });
  }
 dataGridView1.DataSource = itemStates;

0

这是我从此处复制的答案。

只需要再像这样填充数据网格:

this.XXXTableAdapter.Fill(this.DataSet.XXX);

如果您使用dataGridView的自动连接功能,此代码会自动在Form_Load()中创建。

0

删除所有行后再填充:

BindingList<ItemState> itemStates = new BindingList<ItemState>();
datagridview1.Rows.Clear();

for(int i = 0; i < 10; i++)
{
    itemStates.Add(new ItemState { id = i.ToString() });
}

datagridview1.DataSource = itemStates;
Thread.Sleep(500);


0

你正在循环内设置数据源并在每次添加后休眠500。为什么不先将所有内容添加到itemstates中,然后在添加完毕后再设置数据源呢?如果你想让线程在此之后休眠,那也可以。这里的第一个代码块是你的,第二个代码块是我修改过的。

for (int i = 0; i < 10; i++) { 
    itemStates.Add(new ItemState { Id = i.ToString() });
    dataGridView1.DataSource = null;
    dataGridView1.DataSource = itemStates;
    System.Threading.Thread.Sleep(500);
}

将您的代码更改为以下内容:这样会更快。

for (int i = 0; i < 10; i++) { 
    itemStates.Add(new ItemState { Id = i.ToString() });

}
    dataGridView1.DataSource = typeof(List); 
    dataGridView1.DataSource = itemStates;
    System.Threading.Thread.Sleep(500);

-5

试试这段代码

List itemStates = new List();

for (int i = 0; i < 10; i++)
{ 
    itemStates.Add(new ItemState { Id = i.ToString() });
    dataGridView1.DataSource = itemStates;
    dataGridView1.DataBind();
    System.Threading.Thread.Sleep(500);
}

3
DataBind() 是一个用于数据绑定控件的 ASP .Net 方法。 - Tjaart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接