我有一個特殊的問題實現我自己的集合,它應該支持IBindingList
。使用IBindingList的WinForms中的數據綁定在空列表上失敗
我有一個特定數據類(DataItem
)的集合類(DataCollection
)。該集合實現接口IBindingList
,IList
,IList<DataItem>
和DataItem
實現INotifyPropertyChanged
(並且具有用於數據綁定的公共屬性)。
當我試圖通過設置網格的DataSource
屬性集合到DataGridView
綁定,它工作正常如果集合是不綁定的瞬間空。否則,如果集合爲空,則網格會注意何時向集合添加或刪除行(即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;
我也試圖在我的IBindingList
的AllowNew
返回true
:
注意,當我指定的列發生同樣的錯誤。這沒有可觀察到的影響。
什麼也沒有如下:
var bindingSource = new BindingSource();
bindingSource.DataSource = myList;
this.dataGridView.DataSource = bindingSource;
的問題是,我怎麼能告訴綁定機制來識別我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();
}
}
如果列表的類型是BindingList<DataItem>
它工作正常。如果類型爲BindingList<object>
,則只有在初始化DataSource
時列表不爲空時纔有效。
該解決方案的工作原理非常簡單,我只是找不到它搜索互聯網。非常感謝你!! – thaller 2010-11-22 07:16:25