在 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<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
不会显示新的更新列表。它只显示了我之前添加的两行。
那么问题出在哪里?
每次重新绑定都很好。但是,当我将DataTable
绑定到网格时,每次我对DataTable
进行一些更改时,都不需要重新绑定myGrid
。
如何在不重新绑定的情况下解决?
【问题讨论】:
get; 的访问者必须添加 set; 才能显示 datagridview。 【参考方案1】:这不完全是我遇到的问题,但如果有人希望将任何类型的 BindingList 转换为相同类型的 List,那么它就是这样做的:
var list = bindingList.ToDynamicList();
此外,如果您将动态类型的 BindingLists 分配给 DataGridView.DataSource,请确保首先将其声明为 IBindingList,以便上述工作。
【讨论】:
【参考方案2】:列表没有实现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:当然可以,但是 DataGridView 需要知道您的数据源是否有任何更改。One
方法是使用 BindingList,如果底层列表发生变化,它将引发一个事件。另一种方法是使用 BindingSource
并在每次添加/删除 Row 时调用 ResetBinding() ,但这就是更多工作。如果您想通知 Grid 属性更改,最简单的方法是实现 INotifyPropertyChanged
你为什么使用 BindingList 和 BindingSource 因为我们可以直接将列表绑定到 datagridview 数据源属性。讨论这里使用的 BindingList 和 BindingSource 的重要性。谢谢
@Mou 如果需要,您可以将 DataGrid 绑定到 List<T>
。但是,如果您以编程方式将项目添加到列表中,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<T>
已经实现了它,但不支持排序/过滤。
是的,我同意你的看法。所以我认为 ObservableCollection在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> 添加到列表框的类型错误