I have a dataGridView with 4 columns. 3 of the columns i want to use a combobox. In the datagridview properties from the design view i already set the columns to DataGridViewComboBoxColumns. how do i from the code set the columns values from a dataset?

I can get the data i need in two datasets just don't know how to tie the data from my dataset to the related columns.

Here is what i have so far. I keep getting a error when the grid loads: "DatqaGridView Default Error Dialog. The following exception occurred in the DataGridView: System.ArgumentException:DataGridViewComboBoxCell value is not valid.

private void StoreHardwareListForm_Load(object sender, EventArgs e)
		{
			hardwareBindingSource.DataSource = hardware.Tables[ 0 ];
			dataGridView1.DataSource = hardwareBindingSource;
			
			DataSet hardwareTypes = DAL.FetchData(SQLCoreSelect.HardwareTypes());
			hardwareDescription.DataSource = hardwareTypes;
			hardwareDescription.DisplayMember = "hardwareDescription";
			hardwareDescription.ValueMember = "hardwareTypeID";

			hardwareGroup.DataSource = hardwareTypes;
			hardwareGroup.DisplayMember = "hardwareGroup";
			dataGridView1.ClearSelection();
		}

Dani AI

Generated

The ComboBox error almost always means the value in your bound column does not exist in the ComboBox’s list, or the types do not match. is right that DataPropertyName must point at the column that stores the foreign key, and ’s demo shows the classic repro: if your grid has a value (say 5) that is not present in the lookup table, the cell is invalid. Also watch for type mismatches (string vs int) and nulls; either add a sentinel row like None or handle DataError to diagnose.

Try this binding pattern. Configure the ComboBox columns first, turn off auto-generation, then bind the grid. Ensure the lookup ID column type matches exactly.

// 1) Configure columns before binding the grid
dataGridView1.AutoGenerateColumns = false;

var colDesc = (DataGridViewComboBoxColumn)dataGridView1.Columns["hardwareDescription"];
colDesc.DataSource = hardwareTypesTable;              // DataTable: hardwareTypeID(int), hardwareDescription(string)
colDesc.DisplayMember = "hardwareDescription";
colDesc.ValueMember = "hardwareTypeID";
colDesc.DataPropertyName = "hardwareTypeID";          // bind to FK in the main table
colDesc.ValueType = typeof(int);
colDesc.DefaultCellStyle.NullValue = "(none)";

var colStatus = (DataGridViewComboBoxColumn)dataGridView1.Columns["hardwareStatus"];
colStatus.DataSource = new[] { "active", "loaner", "replaced", "failed", "pending", "not active" };

// 2) Bind the main table
dataGridView1.DataSource = hardwareTable;

// 3) Make column order explicit
dataGridView1.Columns["hardwareTypeID"].Visible = false;
dataGridView1.Columns["hardwareDescription"].DisplayIndex = 0;
dataGridView1.Columns["hardwareGroup"].DisplayIndex = 1;
dataGridView1.Columns["serialNumber"].DisplayIndex = 2;
dataGridView1.Columns["hardwareStatus"].DisplayIndex = 3;

// 4) Surface binding problems instead of the generic dialog
dataGridView1.DataError += (s, e) => {
    System.Diagnostics.Debug.WriteLine($"DataError at {e.ColumnIndex},{e.RowIndex}: {e.Exception.Message}");
    e.ThrowException = false;
};

Tip for the dependent hardwareGroup: handle CurrentCellDirtyStateChanged to commit the new selection immediately, then in CellValueChanged look up the chosen hardwareTypeID in hardwareTypesTable and set the row’s hardwareGroup cell. Keeping ValueMember set will make that lookup trivial and avoids hiding the real issue.

Recommended Answers

All 8 Replies

First set the data source for the combobox column as you would for just a regular combo box. Then set the DataPropertyName property for the combobox column to the name of the column you want to bind to in your data set.

Thanks for the reply. I tried setting this up like a regular combo, and the data still does not display and i get the same datagridview error. This is what i changed

hardwareDescription.DataSource = hardwareTypes.Tables[0];

This is working a bit better now that i changed the order. I set up the combo boxes first, then set the datagridview

I'm still getting this "DataGridView Default Error Dialog. The following exception occurred in the DataGridView: System.ArgumentExceptionataGridViewComboBoxCell value is not valid.
I have removed the datagridview from my form and started from scratch. When i re-add, i was able to pinpoint that the error happens if i set the Valuemember on the combobox. I do this on all my other comboboxes outside a datagridview, so I'm not sure why this causes the exception to be thrown

>System.ArgumentExceptionataGridViewComboBoxCell value is not valid.

Please take a look at this sample,

DataTable dt1 = new DataTable();
            dt1.Columns.Add("Code", typeof(int));
            dt1.Columns.Add("Product");

            dt1.Rows.Add(0, "None");
            dt1.Rows.Add(1, "Foo");
            dt1.Rows.Add(2, "Bar");

            DataTable dt2 = new DataTable();
            dt2.Columns.Add("Code", typeof(int));
            dt2.Columns.Add("Qty", typeof(int));


            DataGridViewComboBoxColumn col1 = new DataGridViewComboBoxColumn();
            DataGridViewTextBoxColumn  col2 = new DataGridViewTextBoxColumn();

            col1.DataSource = dt1;
            col1.DisplayMember = "Product";
            col1.ValueMember = "Code";

            col1.DataPropertyName = "Code";
            col2.DataPropertyName = "Qty";



            //  dt2.Rows.Add(5, 100);   //  This statement causes an error
                                        //  because value 5 is not present in combobox.

            dataGridView1.Columns.Add(col1);
            dataGridView1.Columns.Add(col2);

            dataGridView1.DataSource = dt2;

Thanks you for the reply. i changed my code but I still get exception. If i comment out the value member i do not get the exception.

DataSet hardwareTypes = DAL.FetchData(SQLCoreSelect.HardwareTypes());
			
			hardwareDescription.DataSource = hardwareTypes.Tables[ 0 ];
			hardwareBindingSource.DataSource = hardware.Tables[ 0 ];

			hardwareDescription.DisplayMember = "hardwareDescription";
			hardwareDescription.ValueMember = "hardwareTypeID";
			hardwareDescription.DataPropertyName = "hardwareTypeID";

			hardwareGroup.DisplayMember = "hardwareGroup";
			hardwareGroup.ValueMember = "hardwareTypeID";
			hardwareGroup.DataPropertyName = "hardwareTypeID";

			
			dataGridView1.DataSource = hardwareBindingSource;

			dataGridView1.ClearSelection();

I'm stuck here. Two things I need help on.
1. I need to understand why I keep getting this error: The following exception occurred in the DataGridView: System.FormatException: DataGridViewComboBoxCell value is not valid."
In my code if i comment out line 20 where i set the valueMember i do not get the error. But i need to know what the related hardware id is, because i want to use this to determine the type of group from my hardwareType table.
Basically if the user changes the hardwareDescription from the datagridview via the combobox, i call a function that will update the hardwareGroup cell for that row based on the hardwareTypeID

2. I can not get the columns to display in the order i have them in the designer?

In the designer i have the columns in this order: hardwareTypeID, hardwareDescription, hardwareGroup, serialNumber, hardwareStatus.

hardwareTypeId Visaible is set to false
hardwareDescription, and hardwareStatus ColumnType is set to DataGridViewComboBoxColumn
hardwareGroup is a readonly column
This is what my sql query looks like:

select sh.hardwareStatus, h.serialNumber, ht.hardwareTypeID, ht.hardwareDescription, ht.hardwareGroup from storehardware sh join store s ON s.storeID = sh.storeID join  hardware h ON sh.hardwareID = h.hardwareID join hardwaretype ht ON ht.hardwareTypeID = h.hardwareTypeID WHERE s.storeID=@storeID

When i run the code, i keep getting "The following exception occurred in the DataGridView: System.FormatException: DataGridViewComboBoxCell value is not valid."

When the datagridview displays the columns are in this order: hardwareDescription, hardwareGroup, hardwareStatus, serialNumber

Please let me know what is wrong with my code!! I'm just not getting this.

private BindingSource hardwareBindingSource = new BindingSource();
private DataSet hardware = new DataSet();
private DbDataAdapter adapter;

		/// <summary>
		/// Default constructor
		/// </summary>
		/// <param name="rowDetails">A DbDataAdapter that contains select, update, and insert statements</param>
		public StoreHardwareListForm(DbDataAdapter storeHardwareAdapter)
		{
			InitializeComponent();
			adapter = storeHardwareAdapter;			
		}

private void StoreHardwareListForm_Load(object sender, EventArgs e)
		{
                        //description combobox
			DataSet hardwareTypes = DAL.FetchData(SQLCoreSelect.HardwareTypes());
			hardwareDescription.DataSource = hardwareTypes.Tables[ 0 ];
			hardwareDescription.ValueMember = "hardwareTypeID";
			hardwareDescription.DisplayMember = "hardwareDescription";

                        //status combobox
			hardwareStatus.Items.Add("active");
			hardwareStatus.Items.Add("loaner");
			hardwareStatus.Items.Add("replaced");
			hardwareStatus.Items.Add("failed");
			hardwareStatus.Items.Add("pending");
			hardwareStatus.Items.Add("not active");

			adapter.Fill(hardware);
			hardwareBindingSource.DataSource = hardware.Tables[0];
			dataGridView1.DataSource = hardwareBindingSource;
			dataGridView1.ClearSelection();
		}

Not going use the ValueMember. I already pass in the id via the hardwareTypeID column

So problem 1 is solved.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.