2011-05-10 31 views
4

我有如下形式的一類:如何將複雜對象綁定到DataGridView?

public class Cat 
{ 
    public string Name { get; set; } 
    public string Description {get; set; } 
    public List<Cheezburger> Cheezbugers { get; private set; } 
}; 

public class Cheezburger 
{ 
    public int PattyCount { get; set; } 
    public bool CanHaz { get; set; } 
}; 

我希望能夠在DataGridView顯示此貓的List如下:

--------------------------------------------------------------------------------- 
| Name  | Description | PattyCount | CanHaz | PattyCount | CanHaz | etc 
-------------------------------------------------------------------------------- 
| Felix | Classic Cat | 1   | true  | 3   | false | etc 
| Garfield | Fat,Lazy Cat | 2   | false | 7   | true | etc 

等等...的目標是列出同一行中的所有CatCheezbuger。如果你只是嘗試綁定Cat的列表,你不會得到這種行爲。

問題是我不知道如何做一個DataGridViewCats.Cheezbugers列表中的單個項目之間的源的複雜綁定。對於它的價值,我確信列表中的每個Cat在其列表中具有相同數量的Cheezbugers。

編輯

我知道DataGridView complex binding問同樣的問題,但接受的答案只能如果我知道有多少項目是在未來的時間列表,事實並非如此。我所知道的是,所有的名單將具有相同的長度。

回答

6

這不僅僅是一個'複雜的綁定',這是一個Pivot,您希望將重複數據的詳細信息(list of'cheezburgers)轉換爲單行,並且該行的未確定數目列。

我相信你最好的選擇是編寫一個自定義序列化程序,它將允許你將數據轉換爲xml數據表中的行,然後綁定到該行。由於你的列數會不一致xml會更寬容,但我不確定DataGridView如何處理它。

編輯FOLLOWS 因爲我沒有「知道」在DataGridView會如何處理XML數據表,我決定把它寫起來並進行測試。我的工作方式如我所料,而且我相信你會如何。

  1. 這裏是你的貓& cheezburger類(略有修改)

    public class Cat 
    { 
        public string Name { get; set; } 
        public string Description { get; set; } 
        public List<Cheezburger> Cheezbugers { get; private set; } 
    
        public void AddCheezburger(Cheezburger cheezburger) 
        { 
         if (this.Cheezbugers == null) 
          this.Cheezbugers = new List<Cheezburger>(); 
         this.Cheezbugers.Add(cheezburger); 
        } 
    }; 
    
    public class Cheezburger 
    { 
        public int PattyCount { get; set; } 
        public bool CanHaz { get; set; } 
    }; 
    
  2. 然後,你需要創建簡單的形式有兩個按鈕「綁定到對象」(按鈕1)和「綁定到數據表」 (button2),將DataGridView錨定到底部。並編寫了類似的形式:

//在編輯這下一行是在代碼塊,一旦我救它,它不是..

public partial class Form1 : Form 
{ 

    List<Cat> cats = new List<Cat>(); 

    public Form1() 
    { 
     InitializeComponent(); 

     cats.Add(new Cat() { Name = "Felix", Description = "Classic Cat" }); 
     cats.Add(new Cat() { Name = "Garfield", Description = "Fat,Lazy" }); 
     cats.Add(new Cat() { Name = "Tom", Description = "Wanna-Be-Mouser" }); 
     cats[0].AddCheezburger(new Cheezburger() { CanHaz = true, PattyCount = 1 }); 
     cats[0].AddCheezburger(new Cheezburger() { CanHaz = false, PattyCount = 3 }); 
     cats[1].AddCheezburger(new Cheezburger() { CanHaz = false, PattyCount = 2 }); 
     cats[1].AddCheezburger(new Cheezburger() { CanHaz = true, PattyCount = 7 }); 
     cats[1].AddCheezburger(new Cheezburger() { CanHaz = true, PattyCount = 99 }); 
     cats[2].AddCheezburger(new Cheezburger() { CanHaz = true, PattyCount = 5 }); 
     cats[2].AddCheezburger(new Cheezburger() { CanHaz = false, PattyCount = 14 }); 

    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     dataGridView1.DataSource = null; 
     dataGridView1.DataSource = cats; 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     dataGridView1.DataSource = null; 
     dataGridView1.DataSource = serializeCats(cats); 
    } 

    private DataTable serializeCats(List<Cat> cats) 
    { 

     DataTable returnTable = new DataTable("Cats"); 
     returnTable.Columns.Add(new DataColumn("Name")); 
     returnTable.Columns.Add(new DataColumn("Description")); 
     int setID = 1; 
     foreach (Cat cat in cats) 
     { 
      //If the row requires more columns than are present then add additional columns 
      int totalColumnsRequired = (cat.Cheezbugers.Count * 2) + 2; 

      while (returnTable.Columns.Count < totalColumnsRequired) 
      { 
       returnTable.Columns.Add(new DataColumn("Can Haz " + setID.ToString())); 
       returnTable.Columns.Add(new DataColumn("Patty Count " + setID.ToString())); 
       setID++; 
      } 
      returnTable.AcceptChanges(); 
      DataRow row = returnTable.NewRow(); 
      row[0] = cat.Name; 
      row[1] = cat.Description; 
      int cbi = 2; //cheezburger index 
      foreach (Cheezburger cheezburger in cat.Cheezbugers) 
      { 
       row[cbi] = cheezburger.CanHaz; 
       cbi++; 
       row[cbi] = cheezburger.PattyCount; 
       cbi++; 
      } 

      returnTable.Rows.Add(row); 
     } 
     return returnTable; 
    } 
} 

不要試圖預先定義DataGridView列,它們將根據數據源動態創建。綁定到貓列表將獲得兩列(名稱/描述)綁定到DataTable獲得8列,名稱&描述+ 6列cheezburger信息,列隊爲(我相信)你想要的。 Cats Haz Cheezeburgers

+0

真棒回答,並提出。 – Anthony 2011-05-11 12:20:18

0

如果我正確地閱讀你的問題,我想你問的是如何顯示每個貓的Cheezbugers項目列表。

從概念上來說,完成此操作的一種方法是將Cheezbugers屬性與網格中的自定義列模板綁定到Repeater。換句話說,在自定義模板網格列中嵌入一箇中繼器並將其綁定到那裏。您可以使用列表項目模式或其他格式來呈現Cheezbugers列表。它將支持列表中的任意數量的項目。

編輯:我剛剛意識到你正在開發的窗體,而不是asp.net。中繼器有一個等效或合理的等效形式 - DataRepeater。可以滿足你的需求。上面的想法是一樣的。

+0

是的,你正確理解我的問題。從來沒有聽說過一個'Repeater',然後去閱讀它。 – Anthony 2011-05-10 19:21:56

+0

我在實現了使用Windows窗體而不是asp.net的工作之後編輯了答案。中繼器方法仍然可以滿足您的需求(請參閱答案)。 – 2011-05-10 20:00:32