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

Posted

技术标签:

【中文标题】在 WinForm 中将 List<T> 绑定到 DataGridView【英文标题】:Binding List<T> to DataGridView in WinForm 【发布时间】:2013-05-17 17:57:01 【问题描述】:

我有课

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

还有一个List&lt;Person&gt;,我在其中添加了一些项目。该列表绑定到我的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 不会显示新的更新列表。它只显示了我之前添加的两行。

那么问题出在哪里?

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

如何在不重新绑定的情况下解决?

【问题讨论】:

get; 的访问者必须添加 set; 才能显示 datagridview。 【参考方案1】:

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

var list = bindingList.ToDynamicList();

此外,如果您将动态类型的 BindingLists 分配给 DataGridView.DataSource,请确保首先将其声明为 IBindingList,以便上述工作。

【讨论】:

【参考方案2】:

列表没有实现IBindingList,所以网格不知道你的新项目。

改为将您的 DataGridView 绑定到 BindingList&lt;T&gt;

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:当然可以,但是 DataGridView 需要知道您的数据源是否有任何更改。 One 方法是使用 BindingList,如果底层列表发生变化,它将引发一个事件。另一种方法是使用 BindingSource 并在每次添加/删除 Row 时调用 ResetBinding() ,但这就是更多工作。如果您想通知 Grid 属性更改,最简单的方法是实现 INotifyPropertyChanged 你为什么使用 BindingList 和 BindingSource 因为我们可以直接将列表绑定到 datagridview 数据源属性。讨论这里使用的 BindingList 和 BindingSource 的重要性。谢谢 @Mou 如果需要,您可以将 DataGrid 绑定到 List&lt;T&gt;。但是,如果您以编程方式将项目添加到列表中,DataGridView 将不会知道它,因为您的列表没有实现IBindingList。关于 BindingSource:我经常使用 winform,除了 BindingSource - FULLSTOP 之外,我不绑定任何其他东西。添加更多细节对于评论来说太过分了,但是BindingSource 可以提供这么多没有任何缺点的东西。我会说Anyone who does not use a BindingSource for binding has not fully understood windows forms databindings @CraigBrett 将BindingSource 视为数据源和 GUI 之间的桥梁。它解决了许多与数据绑定相关的问题。你想重新加载你的数据吗?只需将bindingSource.DataSource 设置为您的新集合,而不是重新绑定每个控件。您的 DataSource 可以为空吗?设置bindingSource.DataSource = typeof(YourClass) 您想要一个可编辑的网格,但您的数据源没有无参数构造函数?只需实现bindingSource.AddingNew 事件并自己创建对象。我在使用 BindingSource 时从未遇到过缺点,但有很多好处。【参考方案3】:

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

这里有非常简单的例子,

http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

【讨论】:

这还不够,如果您实现INotifyPropertyChanged,DataGridView 将显示后台发生的所有属性更改,但它不会知道您是否从源中添加/删除行。为此,有一个IBindingList 接口,并且为了您的方便,一个实现BindingList&lt;T&gt; 已经实现了它,但不支持排序/过滤。 是的,我同意你的看法。所以我认为 ObservableCollection 可以用于此。你怎么看?【参考方案4】:

persons添加新项目后添加:

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

【讨论】:

datagrid下看不到dataSource属性,能告诉我怎么用吗? 此建议可能会导致问题。例如,您会发现单击网格中的项目可能会得到 IndexOutOfRangeException,因为此时数据源为空。最初绑定到 BindingList 并在您的对象上实现 INotifyPropertyChanged 会更明智,因为其他答案表明 如果您立即将其分配给下一行的persons,那么将其分配给null有什么意义?【参考方案5】:

每次向 List 添加新元素时,都需要重新绑定 Grid。 比如:

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属性,能告诉我怎么用吗?

以上是关于在 WinForm 中将 List<T> 绑定到 DataGridView的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中将 List<DataRow> 转换为 List<T>?

如何在 C# 中将 IEnumerable<T> 转换为 List<T>?

在 Windows 窗体中将 list<T> 添加到列表框的类型错误

WinForm程序用使用List对象绑定DataGridView数据源

在Java中将List转换为String输出

winform datagridview 绑定泛型集合变得不支持排序的解决方案