Reputation: 301
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?
Upvotes: 5
Views: 5000
Reputation: 301
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.
Upvotes: 7
Reputation: 323
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.
Upvotes: 1
Reputation: 61
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
}
Upvotes: 4