c# - 如何将复杂对象绑定(bind)到 DataGridView?

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

我希望能够在 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。如果您只是尝试绑定(bind) Cat 的列表,您将不会得到此行为。

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

编辑:

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

最佳答案

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

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

编辑跟随 由于我“不知道”DataGridView 将如何处理 XML 数据表,因此我决定编写并测试它。我按照我的预期工作,我相信你会想要什么。

  1. 这是你的 cat & 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)到对象”(button1) 和“绑定(bind)到数据表”(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 列,它们将根据数据源动态创建。绑定(bind)到猫的列表将为您提供两列(名称/描述) 绑定(bind)到 DataTable 将获得 8 列,名称和描述 + 6 列 cheezburger 信息,按(我相信)您想要的方式排列。 Cats Haz Cheezeburgers

关于c# - 如何将复杂对象绑定(bind)到 DataGridView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5955188/

相关文章:

c# - ASP.NET 按 ID 终止 session

c# - HttpWebRequest.Headers[HttpRequestHeader.Referer] 因错误而失败

data-binding - Grails,使用 session 中的值注入(inject)/填充域对象

.net - grid绑定(bind)排序后的DataView时,如何设置DataGridView的选中行为新增行?

.net - 如何连续循环DataGridView行?

c# - C# 和 foreach 中的枚举

c# - 在 VB.NET 中将字符串转换为日期

Android bindingadapter不更新值

android - 如何因数据绑定(bind)的 safeUnbox 警告而导致构建过程失败

C#:为 DataGridView 列标题创建点击事件