Load a ComboBox at Runtime
Learn how to use a dataset object to load a combobox (or other similar objects) at runtime instead of needing to set anything up at design time.
Have you ever come across a problem that is WAY too simple to be this hard? I recently stumbled into a situation like that. The concept seemed simple enough. I needed to populate a
ComboBox
on a .NET form at runtime. The data that needed to go into it would come in the form of a DataSet
. This can’t be hard, right? ComboBoxes
take DataSet
s at design time so I figured I would just dump the DataSet
in at runtime, set up the DisplayMember
and ValueMember
, and I would be good to go.
I tried to do the following:
'dst is our pre-loaded DataSet. It has
'two fields: ID and Value.
ComboBox1.DataSource = dst
ComboBox1.DisplayMember = "Value"
ComboBox1.ValueMember = "ID"
Unfortunately, this throws the error “Cannot bind to the new display member. Parameter name: newDisplayMember”. So that doesn’t work. I did some research and came across an article that indicated that you needed to assign the DisplayMember
and ValueMember
before the DataSource
was assigned so that it would populate correctly, so I tried it using the following code:
'dst is our pre-loaded DataSet. It has
'two fields: ID and Value.
ComboBox1.DisplayMember = "Value"
ComboBox1.ValueMember = "ID"
ComboBox1.DataSource = dst
This time it actually ran (no exceptions thrown) but when I looked at the items in the ComboBox
, there was only one item (there should have been 10) and its text was “System.Data.DataViewManagerListItemTypeDescriptor
”.
Once again I turned to Google for the answer. This time, I came across an article that pointed out that you needed to specify which table in the DataSet
you were attempting to access. That made sense, so I tried it like so:
'dst is our pre-loaded DataSet. It has
'two fields: ID and Value.
ComboBox1.DataSource = dst.Tables("ComboList")
ComboBox1.DisplayMember = "Value"
ComboBox1.ValueMember = "ID"
Finally, this worked as intended. The ComboBox
populated and the values it returned were correct. What seemed to be a simple problem ended up taking half an hour to resolve.
As a side note, I did run across one more issue that might catch some of you off guard. When it seems like everything is set up right but for some reason the entire list is populated with “System.Data.DataRowView
” entries (or the value of a particular selection comes out as this), you have mis-labeled your column. This is the system’s way of telling you that you made a mistake. Just check the column names and try again.
So, I have a working solution. I looked into extracting this functionality into its own function in order to make my life easier. After I got all done, I wasn’t sure that this added any improvements or if it just changed how I entered the information. I’ll give you the code and let you decide:
'A much simpler call that assumes the table is the first table
'in the DataSet is the correct one and it assumes the first
'column is the identity column and the second one is the data
'column.
Public Sub PopulateCombo(ByRef cbo As Windows.Forms.ComboBox, _
ByVal dst As DataSet)
'Calls the full method using our assumptions
PopulateCombo(cbo, dst, dst.Tables(0).Columns(0).ToString, _
dst.Tables(0).Columns(1).ToString, _
dst.Tables(0).ToString)
End Sub
'The complete method that populates a ComboBox reference with
'data from the created DataSet. This is the full method.
Public Sub PopulateCombo(ByRef cbo As Windows.Forms.ComboBox, _
ByVal dst As DataSet, _
ByVal strValueMember As String, _
ByVal strDisplayMember As String, _
ByVal strTableName As String)
With cbo
.DataSource = dst.Tables(strTableName)
.DisplayMember = strDisplayMember
.ValueMember = strValueMember
End With
End Sub
To call this method, you would use the following code in the OnLoad
section of your Form:
'Load the ComboBox from our DataSet
PopulateCombo(ComboBox1, dst)
So, that turns a few lines into one and it is clearer to read. If you are going to be doing this multiple times, it might be useful. It might also help if you wanted to create a class to manage this method, then add a section for storing DataSet
s. This way, you could load the data from the database once and then call it over and over with the same code. Now it is starting to make sense to do it this way.