tags:

views:

136

answers:

1

I have the following data I want to display in a DataGridView:

DataEntry[] data = new[]{
        new DataEntry(){Name = "A", Entries = new []{ "1", "2"}},
        new DataEntry(){Name = "B", Entries = new []{ "1", "2", "3"}}};

"Name" will be a simple TextBox field, and "Entries" a ComboBox where the items to choose from are the elements in the list.

So in this example there would be 2 rows (below is what the datagridview would look like):

       Name                         Entries

Row1 :    A                    <choice of "1" or "2">
Row1 :    B                    <choice of "1" or "2" or "3">

My question is, how do I bind this data?! I've looked at the DataPropertyName, DisplayMember and ValueMember properties... but just cannot work this one out.

Below is the code as it stands - with a comment where I need to add the magic couple of lines to set the DataSource etc. for the Entries column.

public partial class Form1 : Form
    {
        DataEntry[] data = new[]{
            new DataEntry(){Name = "A", Entries = new []{ "1", "2"}},
            new DataEntry(){Name = "B", Entries = new []{ "1", "2", "3"}}};

        public Form1()
        {
            InitializeComponent();
            dataGridView1.AutoGenerateColumns = false;

            var nameCol = new DataGridViewTextBoxColumn();
            nameCol.DataPropertyName = "Name";

            var entriesCol = new DataGridViewComboBoxColumn();

                    //entriesCol. ???? = "Entries"; !!

            dataGridView1.Columns.AddRange(new DataGridViewColumn[] { nameCol, entriesCol });

            dataGridView1.DataSource = data;   
        }
    }


    public class DataEntry
    {
        public string Name { get; set; }
        public IEnumerable<string> Entries { get; set; }
    }
+1  A: 

Come in this morning, and within 10 minutes I had it working!

Thanks go to this MSDN forum post

Solution is to subscribe to the "DataBindingComplete" event and to then go through each row and set the data source on each ComboBoxCell. It would be nice to have a more elegant solution - but hey - it works!

Below is a working version of the code sample I submitted in the original question:

public partial class Form1 : Form
{
    DataEntry[] data = new[]{
        new DataEntry(){Name = "A", Entries = new []{ "1", "2", "3", "4"}},
        new DataEntry(){Name = "B", Entries = new []{ "1", "2", "3"}}};


    string[] cols = new[] { "col1", "col2" };

    public Form1()
    {
        InitializeComponent();

        dataGridView1.AutoGenerateColumns = false;

        var nameCol = new DataGridViewTextBoxColumn();
        nameCol.DataPropertyName = "Name";

        var entriesCol = new DataGridViewComboBoxColumn();
        entriesCol.Name = "Entries";
        dataGridView1.Columns.AddRange(new DataGridViewColumn[] { nameCol, entriesCol });

        dataGridView1.DataSource = data;
        dataGridView1.DataBindingComplete += new DataGridViewBindingCompleteEventHandler(dataGridView1_DataBindingComplete);
    }

    void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        for (int i = 0; i < dataGridView1.Rows.Count; i++)
        {
            DataGridViewComboBoxCell comboCell = (DataGridViewComboBoxCell)dataGridView1.Rows[i].Cells["Entries"];
            DataEntry entry = dataGridView1.Rows[i].DataBoundItem as DataEntry;

            comboCell.DataSource = entry.Entries;
            comboCell.Value = entry.Entries.First();
        }
    }
}

public class DataEntry
{
    public string Name { get; set; }
    public IEnumerable<string> Entries { get; set; }
}
JohnBarton