使用IBindingList在WinForms中的数据绑定在空列表上失败

时间:2010-11-20 15:53:28

标签: c# winforms data-binding

我在实现自己的集合时遇到了一个特殊问题,该集合应该支持IBindingList

我有一个特定数据类(DataCollection)的集合类(DataItem)。该集合实现了接口IBindingListIListIList<DataItem>DataItem实现INotifyPropertyChanged(并具有数据绑定的公共属性)。

当我尝试通过设置网格的DataGridView属性将集合绑定到DataSource时,它正常工作如果集合在此时不为空捆绑。否则,如果集合为空,则在从集合中添加或删除行(即DataItems)时,网格会注意到,但单元格保持为空。与此问题相关的是,在AutoGenerateColumns=true的情况下,网格无法识别数据类的公共成员,并且无法生成列。

我也尝试过,使用DataItems绑定我的BindingList<DataItem>。在这种情况下,即使列表在设置DataSource时为空,网格也能正常工作。另一方面,如果我使用BindingList<object>(但内容与DataItems相同),则行为与我的DataCollection一样错误。我想问题是,如果在绑定时列表为空,则数据绑定无法正确检测DataItem类型,并且当最终项目被添加到集合时,它也无法在以后恢复。

重要的是,如果集合在绑定时不为空,则它可以正常工作。

请注意,指定列时会发生相同的错误:

this.dataGridView.ReadOnly = true;

this.dataGridView.AutoGenerateColumns = false;
DataGridViewTextBoxColumn column;

column = new DataGridViewTextBoxColumn();
column.DataPropertyName = "Id";
column.HeaderText = "Id";
this.dataGridView.Columns.Add(column);

column = new DataGridViewTextBoxColumn();
column.DataPropertyName = "UserName";
column.HeaderText = "UserName";
this.dataGridView.Columns.Add(column);

this.dataGridView.DataSource = myList;

我还尝试在true的{​​{1}}上返回AllowNew。这没有可观察到的影响。

以下内容也失败了:

IBindingList

问题是,我怎样才能告诉绑定机制识别我的var bindingSource = new BindingSource(); bindingSource.DataSource = myList; this.dataGridView.DataSource = bindingSource;

(谢谢)

更新1:

我做了一个小测试项目,显示了这个问题:

DataItems

如果列表的类型为public partial class Form1: Form { public Form1() { InitializeComponent(); } class DataItem: INotifyPropertyChanged { private int _id; public int Id { get { return _id; } set { if (value != _id) { _id = value; OnPropertyChanged("Id"); } } } private string _userName; public string UserName { get { return _userName; } set { if (value != _userName) { _userName = value; OnPropertyChanged("UserName"); } } } private void OnPropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } public event PropertyChangedEventHandler PropertyChanged; } /// Make a list of type DataItem or object... //BindingList<object> list = new BindingList<object>() { BindingList<DataItem> list = new BindingList<DataItem>() { //new DataItem() { // Id = 1, // UserName = "testuser" //} }; private void Form1_Load(object sender, EventArgs e) { DataGridView dataGridView = new System.Windows.Forms.DataGridView(); dataGridView.Size = new Size(this.Width-20, this.Height-30); dataGridView.AutoGenerateColumns = true; DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "Id"; column.HeaderText = "Id"; dataGridView.Columns.Add(column); this.Controls.Add(dataGridView); dataGridView.DataSource = list; list.Add( new DataItem() { Id = 3, UserName = "admin" } ); // Make some modifications on the data... (new System.Threading.Thread( state => { System.Threading.Thread.CurrentThread.IsBackground = true; System.Threading.Thread.Sleep(2000); this.Invoke( (Action)( () => { list.Add(new DataItem() { Id = 2, UserName = "guest" }); } ) ); System.Threading.Thread.Sleep(2000); this.Invoke( (Action)( () => { DataItem user = (list.First( obj => ((DataItem)obj).Id == 3 )) as DataItem; user.UserName = "Administrator"; } ) ); })).Start(); } } ,则它可以正常工作。如果类型为BindingList<DataItem>,则仅在初始化BindingList<object>时列表不为空时才有效。

1 个答案:

答案 0 :(得分:7)

数据绑定将首先查看列表项以尝试获取其属性,但是对于空列表,它将从列表项的Type获取其所有信息。如果使用空BindingList<object>,数据绑定无法发现任何属性的原因是object没有可绑定属性。

要完全确保您的DataCollection类正确支持绑定,即使是空的,也要实现ITypedList接口。它包含方法GetItemProperties(),它允许您显式声明哪些属性是可绑定的。在此方法中,您可以使用以下命令返回DataItem上的属性:

return TypeDescriptor.GetProperties(typeof(DataItem));

这样,即使集合为空,数据绑定也会知道要显示的属性。