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

时间:2011-05-10 19:13:06

标签: c# data-binding 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; }
};

我希望能够在List中显示DataGridView Cats,如下所示:

---------------------------------------------------------------------------------
| 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在其列表中都有相同数量的Cheezbuger

修改

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

2 个答案:

答案 0 :(得分:6)

这不仅仅是一个“复杂绑定”,这是一个 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<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. 然后你需要创建一个简单的表单,其中包含两个按钮“bind to object”(button1)和“bind to datatable”(button2),DataGridView固定在底部。并编写如下表格:

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

    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列,名称&amp;描述+ 6列cheezburger信息,排列为(我相信)你想要的。 Cats Haz Cheezeburgers

答案 1 :(得分:0)

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

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

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