0

I've got a form with a DataGridView thats bound to an business Object that inherits a bindinglist. Note the DGV is not bound direct to a database.

I've got it working well using text boxes, but now need to add a ComboBox in the first viewable column.

Currently, the columns are set using the VB IDE and I've set the first viewable one to be a DataGridViewComboBoxColumn.

Showing IDE setup column as DataGridViewComboBoxColumn

When form loads, it calls a function that sets the datasource of the DGV to an Object, then sets the dataPropertyName of each column to the various properties of the Object-BindingList

        myPurchaseOrderItems.getCPOItems(myPurchaseOrder.id)
        dgvPurchaseOrderItems.AutoGenerateColumns = False
        dgvPurchaseOrderItems.DataSource = myPurchaseOrderItems

        dgvPurchaseOrderItems.Columns(0).DataPropertyName = "cpo_id"
        dgvPurchaseOrderItems.Columns(1).DataPropertyName = "id"
        dgvPurchaseOrderItems.Columns(2).DataPropertyName = "product_code"
        dgvPurchaseOrderItems.Columns(3).DataPropertyName = "description" 
                     etc

The first two columns are not visible. I have a property called product_code that will fill the Product Column OK if I set the Product Code Column to a DataGridViewTextBoxColumn.

However, when I set the column to DataGridViewComboBoxColumn in the IDE. I get a System.ArgumentException: DataGridViewComboBoxCell value is not valid. Not surprising as I havent populated the ComboBox.

How can I populate it?

I've seen Adding and Populating DataGridViewComboBoxcolumn to Bound Datagridview

but this looks like its adding a new column to a DGV. I dont want to do that as I already have the column setup via the IDE and have given it its value.

I can generate a bindinglist with the values that the combobox should have, or just use the results of a sql query. I just dont know how to fill it.

Thanks!

user3844416
  • 125
  • 7
  • What type is `product_code`? Is it a List/Array of values or a single value? You can subscribe to the `DataGridView.DataSourceChanged` event and fill the ComboBox there, since you're sure you have new data (or the DataSource is null, so you skip it or clear it). – Jimi Apr 16 '19 at 19:43
  • You populate it in exactly the same way as you would populate a `ComboBox` control: you set its `DisplayMember`, `ValueMember` and `DataSource` properties. The question you linked to demonstrates exactly that. So what if it also shows how to add a column in code? A column is a column. Once it's added, however that was done, using it is exactly the same. – jmcilhinney Apr 16 '19 at 23:08
  • @jmcilhinney - I tried doing that but when I try adding displaymember to the column it doesnt exist as a property. i.e. if I try creating another line with dgvPurchaseOrderItems.Columns(2). I can't add displaymember, valueMember or datasource to the end of it. – user3844416 Apr 18 '19 at 10:25
  • 1
    If you just index the `Columns` collection of the grid then you get a `DataGridViewColumn` reference back and of course `DisplayMember` is not a member of that type. It is a member of the `DataGridViewComboBoxColumn` class, so you need a reference of that type. That's what casting is for. That said, what are you indexing the `Columns` collection for in the first place? If you added the columns in the designer then you have a dedicated field for each one and, of course, each of those fields is declared as the specific type of each column rather than just `DataGridViewColumn`. – jmcilhinney Apr 18 '19 at 11:34
  • @jmcilhinney - So I need to cast column 2 to a DataGridViewComboBoxColumn? I just find it a bit strange that I've set the Column 2 to a ComboBox in the IDE and have to cast, where as the others that are text, I don't have to. Is it because column has the base properties as a textcol? As for using the designer, I guess I'm more comfortable doing the data bits in the code and the graphical bits in the designer. The list of columns in the code gives me an easy reference in one window when doing some programming in another. Your preference? BTW, how do I set a comment as an answer? – user3844416 Apr 21 '19 at 17:41
  • There's nothing strange about it at all. It doesn't matter what type the object is that you're referring to, just what type the reference is that you're referring to it by. As I said, you are using a reference of type `DataGridViewColumn`. Any members of that type, e.g. `DataPropertyName`, don't require a cast. Any members of a more specific type do require a cast as that type. It's no different to assigning a `String` object to an `Object` variable and then trying to get the `Length` property. `Object` has no such property so it can't be done without a cast. – jmcilhinney Apr 22 '19 at 00:35
  • Why would using the designer give you any less easy reference from another form? It wouldn't. The grid is still the grid. It still has a `Columns` property and, as I said, you would also have a dedicated field for each column that was declared as the most specific type, so there would be no casting required. Apart from that, it's bad practice to be referring directly to controls on a form from another form. It's possible but it's the lazy way. Any access to that grid should be done in the form it's on only. Use public methods/properties to initate that access. – jmcilhinney Apr 22 '19 at 00:38
  • I dont mean programmatically referring via other forms. I mean having a list of indexed columns in a code window I can refer to whilst working on code further on down the code window. Whereas looking at the details in the DGVs Collection dialog box means finding that property, opening it up etc. Hope that explains it. – user3844416 Apr 23 '19 at 13:54

0 Answers0