如何将复杂对象绑定到DataGridView?

我有一个遵循表格的类:

public class Cat { public string Name { get; set; } public string Description {get; set; } public List Cheezbugers { get; private set; } }; public class Cheezburger { public int PattyCount { get; set; } public bool CanHaz { get; set; } }; 

我希望能够在DataGridView显示一个Cats 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 

等等……目标是在同一行列出所有Cat ‘s Cheezbuger 。 如果您只是尝试绑定Cat的列表,则不会出现此行为。

问题是我无法弄清楚如何在DataGridViewCats.Cheezbugers列表中的各个项之间执行复杂的源绑定。 值得一提的是,我确信列表中的每只Cat在其列表中都有相同数量的Cheezbuger

编辑

我知道DataGridView复杂绑定会询问相同的问题,但只有当我知道提前列表中有多少项时,接受的答案才有效,而事实并非如此。 我所知道的是,所有列表都具有相同的长度。

这不仅仅是一个“复杂绑定”,这是一个Pivot ,您希望将详细重复数据(列表’cheezburgers)转换为单行,并且该行具有未确定的列数。

我相信这里最好的选择是编写一个自定义序列化程序,它允许您将数据转换为xml数据表中的行,然后绑定到该行。 由于你的列数不一致,xml会更宽容,但我不确定DataGridView将如何处理它。

编辑后续因为我没有“知道”DataGridView如何处理XML DataTable我决定编写并测试它。 我按照我的预期工作,我相信你会想要的。

  1. 这是你的猫和cheezburger类(略有修改)

     public class Cat { public string Name { get; set; } public string Description { get; set; } public List Cheezbugers { get; private set; } public void AddCheezburger(Cheezburger cheezburger) { if (this.Cheezbugers == null) this.Cheezbugers = new List(); this.Cheezbugers.Add(cheezburger); } }; public class Cheezburger { public int PattyCount { get; set; } public bool CanHaz { get; set; } }; 
  2. 然后你需要创建一个简单的表单,其中有两个按钮“bind to object”(button1)和“bind to datatable”(button2),DataGridView锚定在底部。 并将表单编码为:

//在编辑器中,下一行是在代码块中,一旦我保存它就不是..

 public partial class Form1 : Form { List cats = new List(); 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 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信息,排列为(我相信)你想要的。 猫Haz Cheezeburgers

如果我正确地阅读了你的问题,我想你要问的是如何显示每只猫的Cheezbugers项目列表。

在概念上实现此目的的一种方法是将Cheezbugers属性绑定到具有网格中的自定义列模板的Repeater 。 换句话说,在自定义模板网格列中嵌套转发器并将其绑定到那里。 您可以使用列表项模式或其他格式来显示Cheezbugers列表。 它将支持列表中的任意数量的项目。

编辑:我刚刚意识到你正在开发Windows窗体,而不是asp.net。 表单中的转发器具有等效或合理的等价物 – DataRepeater 。 可以满足您的需求。 上面的想法是一样的。