2010-11-20 26 views
3

我有一個特殊的問題實現我自己的集合,它應該支持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; 

我也試圖在我的IBindingListAllowNew返回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時列表不爲空時纔有效。

回答

7

數據綁定將從查看列表項開始,嘗試獲取其屬性,但對於空列表,它將從列表項的Type中獲取其所有信息。如果您使用空的BindingList<object>,數據綁定無法發現任何屬性的原因是object沒有可綁定屬性。

要完全確保DataCollection類正確支持綁定(即使爲空),請實現ITypedList接口。它包括方法GetItemProperties(),它允許您明確指出哪些屬性是可綁定的。在這個方法中,你可以使用下面就DataItem返回屬性:

return TypeDescriptor.GetProperties(typeof(DataItem)); 

這樣一來,即使集合爲空,數據綁定就知道要顯示的屬性。

+0

該解決方案的工作原理非常簡單,我只是找不到它搜索互聯網。非常感謝你!! – thaller 2010-11-22 07:16:25