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

发布于 2024-11-06 14:59:05 字数 1287 浏览 0 评论 0原文

我有一个遵循以下形式的类:

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 列表,您将不会出现此行为。

问题是我不知道如何在 DataGridView 和 Cats.Cheezbugers 列表中的各个项目之间进行复杂的源绑定。就其价值而言,我确信列表中的每只 Cat 都有相同数量的 Cheezbuger

编辑

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

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; }
};

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

And so on... The goal being to list out all the Cat's Cheezbugers in the same row. If you simply try binding the list of Cats you won't get this behavior.

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 Cheezbugers in its list.

Edit:

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

迷路的信 2024-11-13 14:59:05

这不仅仅是一个“复杂的绑定”,这是一个数据透视,您希望将详细的重复数据(芝士汉堡列表)转换为单行,并且该行有一个不确定的数字列。

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

编辑如下
由于我不“知道”DataGridView 如何处理 XML DataTable,所以我决定将其编写并测试它。我按照我期望的方式工作,我相信你也会按照你想要的方式工作。

  1. 这是你的猫和; cheezburger 类(稍作修改)

    公共类猫
    {
        公共字符串名称{获取;放; }
        公共字符串描述{获取;放; }
        公共列表 Cheezbugers { 得到;私人套装; }
    
        公共无效AddCheezburger(Cheezburger cheezburger)
        {
            if (this.Cheezbugers == null)
                this.Cheezbugers = new List();
            this.Cheezbugers.Add(cheezburger); 
        }
    };
    
    公开课芝士汉堡
    {
        公共 int PattyCount { 得到;放; }
        公共 bool CanHaz { 获取;放; }
    };
    
  2. 然后,您需要创建带有两个按钮“绑定到对象”(button1) 和“绑定到数据表”(button2) 的简单表单,并将 DataGridView 锚定到底部。并对表单进行编码,如下所示:

//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 列,它们将根据数据源动态创建。绑定到猫列表将获得两列(名称/描述)绑定到数据表将获得 8 列,名称和描述。描述 + 6 列芝士汉堡信息,按照(我相信)您想要的方式排列。
猫哈兹芝士汉堡

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.

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.

EDIT FOLLOWS
Since 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.

  1. 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; }
    };
    
  2. 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;
    }
}

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.
Cats Haz Cheezeburgers

追我者格杀勿论 2024-11-13 14:59:05

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

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

编辑:我刚刚意识到你正在Windows窗体中开发,而不是asp.net。在表单中存在与中继器等效或合理的等效项 - 数据中继器。可能会满足您的需求。上面的想法是一样的。

If I read your question correctly, I think what you're asking is how to display the list of Cheezbugers items for each cat.

One way conceptually to accomplish this is to bind the Cheezbugers property to a Repeater with a custom column template in the grid. In other words nest a repeater in a custom template grid column and bind it there. You could use a list item pattern or other format to present the list of Cheezbugers. It would support any number of items in the list.

EDIT: I just realized you are developing in windows forms, not asp.net. There is an equivalent or reasonable equivalent to the repeater in forms - DataRepeater. Could possible meet your needs. Idea above is the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文