将List <T>绑定到WinForm中的DataGridView


91

我有一堂课

class Person{
      public string Name {get; set;}
      public string Surname {get; set;}
}

然后List<Person>向其中添加一些项目。该清单已绑定到我的DataGridView

List<Person> persons = new List<Person>();
persons.Add(new Person(){Name="Joe", Surname="Black"});
persons.Add(new Person(){Name="Misha", Surname="Kozlov"});
myGrid.DataSource = persons;

没有问题。myGrid显示两行,但是当我向persons列表中添加新项目时,myGrid不会显示新的更新列表。它仅显示我之前添加的两行。

那是什么问题呢?

每次重新绑定效果很好。但是当我将a绑定DataTable到网格时,每次进行一些更改时,DataTable都不需要ReBind myGrid

如何解决问题而不每次都重新绑定?

Answers:


187

列表未实现,IBindingList因此网格不知道您的新项目。

将您的DataGridView绑定到BindingList<T>

var list = new BindingList<Person>(persons);
myGrid.DataSource = list;

但我什至会更进一步,将您的网格绑定到 BindingSource

var list = new List<Person>()
{
    new Person { Name = "Joe", },
    new Person { Name = "Misha", },
};
var bindingList = new BindingList<Person>(list);
var source = new BindingSource(bindingList, null);
grid.DataSource = source;

它说,你可以使用的IList等接口藏汉:msdn.microsoft.com/en-us/library/...
Pacane

4
@Pacane:可以,但是DataGridView需要知道您的数据源是否有任何更改。One使用BindingList的方法,如果基础列表发生更改,它将引发一个事件。另一种方法是使用a BindingSource并在每次添加/删除行时调用ResetBinding(),但这可以完成更多工作。如果你想告知电网有关属性更改的最简单的方法是实施INotifyPropertyChanged
于尔根Steinblock

5
您为什么使用BindingList和BindingSource,因为我们可以将列表直接绑定到datagridview的datasource属性。讨论此处使用的BindingList和BindingSource的重要性。感谢

5
@Mou如果需要,可以将DataGrid绑定到List<T>。但是,如果您以编程方式向列表中添加项目,则DataGridView不会知道它,因为您的List并不是无礼的IBindingList。关于BindingSource:我经常使用Winforms,除了BindingSource-FULLSTOP,我不绑定任何其他东西。添加更多细节对于评论来说太多了,但BindingSource提供了很多好处而没有任何缺点。我会走这么远说Anyone who does not use a BindingSource for binding has not fully understood windows forms databindings
尔根·斯坦伯格

4
@CraigBrett可以将其BindingSource视为数据源和GUI之间的桥梁。它解决了许多与数据绑定有关的问题。您想重新加载数据吗?只需设置bindingSource.DataSource为新集合,而不是重新绑定每个控件即可。您的数据源可以为空吗?设置bindingSource.DataSource = typeof(YourClass)您想拥有一个可编辑的网格,但是您的数据源没有无参数的构造函数?只需实现bindingSource.AddingNew事件并自己创建对象即可。使用时我从未经历过不利的一面,BindingSource但受益匪浅。
尔根·斯坦伯格

4

每次将新元素添加到列表时,都需要重新绑定网格。就像是:

List<Person> persons = new List<Person>();
persons.Add(new Person() { Name = "Joe", Surname = "Black" });
persons.Add(new Person() { Name = "Misha", Surname = "Kozlov" });
dataGridView1.DataSource = persons;

// added a new item
persons.Add(new Person() { Name = "John", Surname = "Doe" });
// bind to the updated source
dataGridView1.DataSource = persons;

我在datagrid下看不到dataSource属性。能否告诉我如何使用它?
RSB 2015年

2

是的,可以通过实现INotifyPropertyChanged接口来进行重新绑定。

这里有一个非常简单的例子,

http://msdn.microsoft.com/zh-CN/library/system.componentmodel.inotifypropertychanged.aspx


1
这还不够,如果实现INotifyPropertyChanged了DataGridView,将显示在后台发生的所有属性更改,但是它不知道是否从源中添加/删除行。为此,有一个IBindingList接口,为了您的方便起见,有一个BindingList<T>已实现的接口,但不支持排序/过滤。
于尔根Steinblock

1
是的,我同意你的看法。所以我认为ObservableCollection <T>可以用于此目的。你怎么看?
开发人员

0

添加新项目后persons添加:

myGrid.DataSource = null;
myGrid.DataSource = persons;

我在datagrid下看不到dataSource属性。能否告诉我如何使用它?
RSB

1
这个建议可能会引起问题。例如,您可能会发现,单击网格中的某个项目可能会获得IndexOutOfRangeException,因为此时数据源为null。最初绑定到BindingList并在对象上实现INotifyPropertyChanged会更明智,因为其他答案表明
Steve 2015年

null如果立即persons在下一行将其分配给它,那么分配给它的意义何在?
Rufus L

0

这不完全是我遇到的问题,但是如果有人希望将任何类型的BindingList转换为相同类型的List,则可以这样做:

var list = bindingList.ToDynamicList();

另外,如果要将动态类型的BindingList分配给DataGridView.DataSource,请确保首先将其声明为IBindingList,以便上面的方法起作用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.