2011-05-10 68 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

相关问题