This is not just a “complex binding”, it is a Pivot where you want to convert the details of repeating data (list o "cheezburgers") into one row, and this row has an undefined number of columns.
I believe that your best option here is to write your own serializer, which will allow you to convert your data to strings in xml format, and then bind to it. Since the number of columns will be incompatible, xml will be more forgiving, although I'm not sure how the DataGridView will handle it.
EDIT FOLLOWING Since I did not "know" how the DataGridView processed the XML DataTable, I decided to write it and test it. I work as I expected, and I believe as you want.
Here are your cat and 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; } };
Then you need to create a simple form with two buttons “bind to object” (button1) and “bind to datatable” (button2), while the DataGridView is bound to the base. and enter the form code:
// in the editor, this next line is in the code block, as soon as I save it, it’s not.
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) {
Do not try to predefine the columns of the DataGridView, they will be created dynamically based on the data source. Binding to the list of cats will give you two columns (name / description). Linking to a DataTable gets 8 columns, name and description + 6 columns of cheezburger information, arranged as you think. 