2010-11-20 9 views
3

IBindingListをサポートする必要がある自分のコレクションを実装するのに特に問題があります。IBindingListを使用したWinFormsでのデータバインディングが空のリストで失敗する

特定のデータクラス(DataItem)のコレクションクラス(DataCollection)があります。コレクションは、IBindingList,IListIList<DataItem>DataItemの各インターフェイスを実装しています。INotifyPropertyChanged(データバインディングにはパブリックプロパティを持ちます)。

私は、グリッドのDataSourceプロパティを設定することにより、DataGridViewにコレクションをバインドしようとすると、それが正しくかのコレクションは結合の瞬間に空ではありません動作します。そうでない場合、コレクションが空の場合、グリッドは行(つまり、DataItems)がコレクションに追加または削除されたときにセルが空のままであることに気づきます。問題は、AutoGenerateColumns=trueの場合、グリッドがデータクラスのパブリックメンバーを認識できず、列を生成できないことです。

私が試したことは、BindingList<DataItem>を使用してDataItemsをバインドします。その場合、グリッドは、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; 

私もIBindingListAllowNewtrueを返すようにしようとしました。それには目に見える影響はなかった。また、失敗した何

は以下の通りです:

var bindingSource = new BindingSource(); 
bindingSource.DataSource = myList; 
this.dataGridView.DataSource = bindingSource; 

、どのように私は私のDataItemsを認識するための結合メカニズムを伝えることができている質問?リストの種類は、それが正常に動作するBindingList<DataItem>ある場合

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(); 
    } 
} 

:私は問題を示して小さなテストプロジェクトを作っ

UPDATE 1を(ありがとうございます)。タイプがBindingList<object>の場合は、DataSourceを初期化するときにリストが空でない場合にのみ機能します。

答えて

7

データバインディングは、リスト項目を調べてプロパティを取得することから開始しますが、空のリストの場合はリスト項目のTypeからすべての情報を取得します。空のBindingList<object>を使用すると、データバインディングがプロパティを検出できない理由は、objectにはバインド可能なプロパティがありません。

DataCollectionクラスがバインドを適切にサポートしていることを完全に確認するには、空の場合でもITypedListインターフェイスを実装します。メソッドGetItemProperties()が含まれており、バインド可能なプロパティを明示的に指定できます。この方法の中で、あなたはDataItemのプロパティを返すために、次を使用することができます。

return TypeDescriptor.GetProperties(typeof(DataItem)); 

この方法では、コレクションが空の場合でも、データバインディングは、表示するプロパティを知っているだろう。

+0

解決策は非常に簡単で、私はそれをインターネットで検索することができませんでした。どうもありがとうございました!! – thaller

関連する問題