Load a ComboBox from a Stored Procedure

Article ID: 56932

Justin Taylor sent me the following message: "I need to populate a .NET combo box with the results of a System i stored procedure. The best I can come up with is to read the iDB2DataReader results and load them into an ArrayList and then process the elements of the ArrayList and load a String array and set the combo box DataSource equal to the String array. That is extremely convoluted, and I am sure there is a better way."

Figure 1 shows an example of a combo box control on a Windows form. There is an equivalent .NET control available for web forms, so you can use the same technique to load the combo box. When you do so, you can set two properties: the DisplayMember and the ValueMember. The DisplayMember is the data that is actually displayed to the user. The ValueMember contains the value that is returned to your program when you select the corresponding combo box item.

Justin is on the right track with moving his data into a string array. The MSDN documentation for the DataSource property for a combo box shows that you can load a combo box by setting its DataSource property to "an object that implements the IList interface, such as a DataSet or an Array." The IList interface is used by controls to iterate over a collection, such as a DataSet or an Array.

The problem is that by using the System i .NET Data Provider to return data in an iDB2DataReader, you need to extract the data from the data reader into an object that implements IList. If you look into the MSDN documentation, you see that the System.Data.IDataReader interface (implemented by the iDB2DataReader class) does not implement IList; IDataReader implements IDisposable and IDataRecord. An array does implement IList, so by moving the data from the iDB2DataReader into an array, the combo box data source can iterate over the array.

As Justin concludes, that seems to be the long way around. After all, the combo box property is named DataSource, so it would seem that you should be able to work more directly with data right from a database.

The example code in Figure 2 shows one possible solution. In this example, the action occurs in the Form_Load subroutine to load the combo box when the form is initially loaded. An iDB2Connection object is defined and then opened, followed by an iDB2Command that points to a stored procedure named sp_qcustcdt. The code for that stored procedure is not shown; it is a simple SQL SELECT statement that returns all rows from the QIWS.QCUSTCDT table. The fact that a stored procedure is used is inconsequential; the technique shown will work for either a stored procedure that returns a result set or an SQL SELECT statement that is embedded within the program.

Rather than bring the results into an iDB2DataReader, an iDB2DataAdapter is used to invoke the command (run the stored procedure) and then to fill a DataSet object. At this point, you have an object (the data source) that implements the IListSource interface, which the MSDN documentation states can be used to return a list that can be bound to a data source.

After filling the data source object, all that remains is to set the combo box data source to the data set and then assign the DisplayMember and ValueMember properties. Note that the data source object contains a table, which is referred to as Tables(0). Within the table, you can refer to columns by column name (as is done in the example) or by column position within the result set.

The one downside I found to using the DataSource with the combo box is that I am prohibited from adding additional item. For example, I would like to place an item at combo box position 0 (the first item in the list) to indicate that the user should select an item. However, when you use a DataSource, you are limited to only having items that are within the DataSource.

Craig: I have used DataSource to populate a combo box and have found a workaround to your inability to add additional items. Once Table(0) of the dataset is populated with the "real" data, I then populate another table [I use table(1) in the dataset] with the data that will be displayed. I create table (1) with two columns: KEY and DATA. Before I read the "real" data, I create a dummy first row with DATA set to a string such as "Please select an item." Then I read my "real" data and populate the rows of the table one by one. At the end, I create a dummy last row with DATA set to a string such as "END OF DATA." I then point DataSource to table(1), DisplayMember to DATA, and ValueMember to KEY. This also works well if you want the DisplayMember to be a formatted concatenated string, such as Name, Address, Phone, etc.

ProVIP Sponsors

ProVIP Sponsors