Question

I'm adding a DataGridViewComboBoxColumn to a DataGridView during the form's Load event handler and setting the DataSource of each DataGridViewComboBoxCell in the columns. However, once the form is shown, the DataSource of each DataGridViewComboBoxCell has been set to null. Here is the code I use to populate the column and it's cells:

DataGridViewComboBoxColumn comboCol;

comboCol = new DataGridViewComboBoxColumn();
comboCol.Name = "ComboCol";
comboCol.HeaderText = "Combo Column";
comboCol.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

this.dgv.Columns.Add(comboCol);

for (int i = 0; i < dgv.Rows.Count; i++)
{
    // This datatable is actually populated here!
    DataTable myData = PopulatedDataTable(dgv.Rows[i].Cells["info"].Value); 

    DataGridViewComboBoxCell DCC = new DataGridViewComboBoxCell();

    DCC = (DataGridViewComboBoxCell)dgv.Rows[i].Cells["CombolCol"];
    DCC.DataSource = myData;

    DCC.DisplayMember = "Association"; // Association is a column in myData
    DCC.ValueMember = "Association";
}

dgv.Columns["association"].Visible = false;

This code does exactly what is expected if I put it in a button that I click AFTER the form has loaded, but when executed during form load the DataSource is cleared. Any suggestions?

Was it helpful?

Solution

I ended up fixing this issue by handling the DataBindingComplete event of the datagrid.

Apparently when you populate a datagrid during a form's Load event, the data in the datagrid gets rebound. This screwed up the data in the unbound column I was trying to add.

By placing my code above in the DataBindingComplete event handler (and disabling the event handler at the beginning and re-enabling it at the end of the event) the columns are added at the appropriate time, and their data isn't scrambled by .NET's foolishness.

OTHER TIPS

Yes, I struggled with it for two days and finally the DataBinding Event fixed it.

Here is the complete code to add a combo box cell to some cells on a DataGridView.

    private void LoadGrid()
    {
        DataTable dtbl = new DataTable();
        dtbl.Columns.Add("FieldNo");
        dtbl.Columns.Add("FieldValue");

        for (int i = 0; i < 10; i++)
        {
            DataRow dr = dtbl.NewRow();
            dr["FieldNo"] = i;
            dr["FieldValue"] = "Name " + i.ToString();
            dtbl.Rows.Add(dr);
        }

        dataGridView1.DataSource = dtbl;
        dataGridView1.DataError += new DataGridViewDataErrorEventHandler(dtgv_ComboDataError);
    }

    private void dtgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        for (int i = 0; i < dataGridView1.Rows.Count; i++)
        {
            if (i % 2 == 0)
            {
                DataGridViewComboBoxCell dCmb = new DataGridViewComboBoxCell();
                dCmb.Items.Add("Yes");
                dCmb.Items.Add("No");
                dCmb.Value = dCmb.Items[0];
                dataGridView1["FieldValue", i] = dCmb;

                ((DataGridViewComboBoxCell)dataGridView1["FieldValue", i]).DisplayStyle = DataGridViewComboBoxDisplayStyle.ComboBox;
            }
        }
    }

    void dtgv_ComboDataError(object sender, DataGridViewDataErrorEventArgs e)
    {
        //Nothing needed here
    } 

I have been struggling with a very similar problem on a DataGridView with a DataGridViewComboBoxColumn.

The DataGridView is bound to a DataSet The DataGridViewComboBoxCell cell drop down options are to be filled according to the value of another cell of the same row.

Whether I fill in the ComboBox Cell Items manually (DataGridViewComboBoxCell.Items property) or use DataBinding (DataGridViewComboBoxCell.DataSource property), right before entering the CellFormatting event handler the values are correct, but as soon as the execution steps in the handler, myComboBoxCell.Items.Count goes down to zero.

If the Value of the cell is anything else than DBNull.Value, this throws a nasty "System.ArgumentException: DataGridViewComboBoxCell value is not valid". (Because the myComboBoxCell.Value is not contained by myComboBoxCell.Items)

My "solution" is more of a workaround: I handle the DataGridView.DataError event and fill in the concerned DataGridComboBoxCell DataSource within that handler. Then cancel the exception (e.ThrowException = False).

It is a bit too dirty to my liking but it works.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top