tha*_*ler 3 c# data-binding winforms
我有一个特殊的问题,实现我应该支持的自己的集合IBindingList.
我有一个DataCollection特定数据类(DataItem)的集合类().集合实现接口IBindingList,IList,IList<DataItem>和DataItem工具INotifyPropertyChanged(和具有公共属性的数据绑定).
当我尝试DataGridView通过设置DataSource网格的属性将集合绑定到a时,如果集合在绑定时不为空,则它可以正常工作.否则,如果集合为空,则在DataItems从集合中添加或删除行(即)时,网格会注意到,但单元格保持为空.与此问题相关的是,网格无法识别数据类的公共成员, AutoGenerateColumns=true并且无法生成列.
我也尝试过,DataItems使用a 绑定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;
Run Code Online (Sandbox Code Playgroud)
我也试图返回true在AllowNew我的IBindingList.这没有可观察到的影响.
还失败的是以下内容:
var bindingSource = new BindingSource();
bindingSource.DataSource = myList;
this.dataGridView.DataSource = bindingSource;
Run Code Online (Sandbox Code Playgroud)
问题是,我怎样才能告诉绑定机制识别我的DataItems?
(谢谢)
更新1:
我做了一个小测试项目,显示了这个问题:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
如果列表的类型是BindingList<DataItem>正确的.如果类型是BindingList<object>它只有在初始化时列表不为空时才有效DataSource.
数据绑定将首先查看列表项以尝试获取其属性,但是对于空列表,它将从Type列表项中获取其所有信息.如果使用空,BindingList<object>则数据绑定无法发现任何属性的原因是object没有可绑定属性.
要完全确保您的DataCollection类正确支持绑定,即使是空的,也要实现该ITypedList接口.它包括该方法GetItemProperties(),该方法允许您显式声明哪些属性是可绑定的.在此方法中,您可以使用以下命令返回以下属性DataItem:
return TypeDescriptor.GetProperties(typeof(DataItem));
Run Code Online (Sandbox Code Playgroud)
这样,即使集合为空,数据绑定也会知道要显示的属性.