问题描述
我有一个遵循以下形式的类:
I have a class that follows the form:
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
的猫,如下所示:
I want to be able to display a List
of Cats this in a DataGridView
as follows:
---------------------------------------------------------------------------------
| 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
的Cheezbuger
.如果您只是尝试绑定 Cat
的列表,您将不会得到这种行为.
And so on... The goal being to list out all the Cat
's Cheezbuger
s in the same row. If you simply try binding the list of Cat
s you won't get this behavior.
问题是我不知道如何在 DataGridView
和 Cats.Cheezbugers
列表中的各个项目之间进行复杂的源绑定>.就其价值而言,我确信列表中的每个 Cat
在其列表中都有相同数量的 Cheezbuger
.
The problem is that I can't figure out how to do a do a complex binding of source between the DataGridView
and the individual items in the list of Cats.Cheezbugers
. For what its worth, I know for sure that each Cat
in the list has the same number of Cheezbuger
s in its list.
编辑:
我知道 DataGridView 复杂绑定 提出了同样的问题,但接受的答案仅适用于我提前知道列表中有多少项目,但事实并非如此.我所知道的是所有列表的长度都相同.
I am aware that DataGridView complex binding asks the same question, but the accepted answer works only if I know how many items are in the list ahead of time, and that is not the case. All I know is that all the lists will have the same length.
推荐答案
这不仅仅是一个复杂绑定",这是一个 Pivot,您希望在其中转换细节重复数据(list o' cheezburgers) 到单行,并且该行的列数不确定.
This isn't just a 'complex binding' this is a Pivot, where you are wanting to transform detail repeating data (the list o' cheezburgers) to a single row, and that row has an undetermined number of columns.
我相信您最好的选择是编写一个自定义序列化程序,它允许您将数据转换为 xml 数据表中的行,然后绑定到该行.由于您的列数将不一致 xml 会更宽容,但我不确定 DataGridView 将如何处理它.
I believe your best option here is to write a custom serializer that will allow you to transform your data into rows in an xml datatable and then bind to that. Since your column count is going to be inconsistent xml will be more forgiving, though I am not sure how the DataGridView will handle it.
编辑以下内容由于我不知道"DataGridView 将如何处理 XML DataTable,因此我决定编写它并对其进行测试.我按照我的预期工作,我相信你会想要的.
EDIT FOLLOWSSince I did not 'know' how the DataGridView would handle the XML DataTable I decided to write it up and test it. I works how I expected, and I believe how you will want.
这是你的猫 &cheezburger 类(略有修改)
Here are your cat & cheezburger classes (slightly modified)
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; }
};
然后您需要创建带有两个按钮绑定到对象"(button1)和绑定到数据表"(button2)的简单表单,并在底部固定一个 DataGridView.并编写如下形式的代码:
Then you need to create simple form with two buttons "bind to object" (button1) and "bind to datatable" (button2), with a DataGridView anchored to the bottom. and code up the form like:
//在编辑器中,下一行在代码块中,一旦我保存它就不是..
//in the editor this next line is in the codeblock, once I save it it isn't..
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 列,它们将根据数据源动态创建.绑定到 cat 列表会得到两列(名称/描述)绑定到 DataTable 会得到 8 列,name &描述 + 6 列 Cheezburger 信息,按(我相信)您想要的方式排列.
Do not attempt to predefine the DataGridView columns, they will be created dynamically based on the data source. Binding to the list of cats will get you two columns (name/description) Binding to the DataTable gets 8 columns, name & description + 6 columns of cheezburger info, lined up as (I believe) you want.
这篇关于如何将复杂对象绑定到 DataGridView?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!