One of the most frequent questions I get regarding data binding is how to hook up a combo box with a data bound list of selections from a related table or collection, and have selections in that combo box set a corresponding value in the related collection. For example, in the following form, the main collection is the Products table from Northwind. The textboxes are displaying a couple of the columns from that table, and the combo box is displaying the supplier name from the related Suppliers table. Products contains a foreign key column with a SupplierID that makes the link.
The code required to hook all this up in .NET 2.0 is very simple, although maybe slightly difficult to discover on your own. The solution below binds the controls to two BindingSource components, which is the new way of doing data binding in .NET 2.0. The BindingSource component provides a layer of indirection between your bound controls and their data sources that makes synchronizing bound controls easier, allows you to switch out the data source without needing to re-initialize bindings, and exposes a number of useful events to monitor what is going on in bound data sources in your code.
Basically all you need to do is get your data and set that as the data source on the two binding sources. Then set up a normal ComboBox data binding on the ComboBox with the DataSource, DisplayMember, and ValueMember properties. You then add a simple binding to the control’s DataBindings collection (an instance of a Binding object) that ties the SelectedValue property on the ComboBox to the corresponding foreign key property/column in the parent collection:
// Retrieve the data for products and suppliers into a data set or custom collections
// Set up the data bindings for the textboxes on the form to their binding source
// i.e. mProductNameTextBox.DataBindings.Add(“Text”, mProductsBindingSource, “ProductName”, true);
// Set the BindingSource.DataSource property for the textboxes on the form
mProductsBindingSource.DataSource = mProducts; // some collection of products
// Set the binding properties for the combo box
mSuppliersBindingSource.DataSource = mSuppliers; // some collection of suppliers
mSuppliersCombo.DataSource = mSuppliersBindingSource;
m_SuppliersCombo.DisplayMember = “CompanyName”;
m_SuppliersCombo.ValueMember = “SupplierID”;
//Add a simple binding for the combo box SelectedValue property to the other collection
The ComboBox databinding takes care of setting the SelectedValue property on the ComboBox whenever the current item in the parent collection changes.
The steps to regenerate thedisplayed sample in the Visual Studio 2005 designer are as follows:
- Create a Database Data Source (typed data set) through the Data Sources window to Northwind with Products and Suppliers tables in it.
- In the Data Sources window, change the control mapping for the Products table to Details (drop down the list of controls by selecting it and dropping it down)
- Set the control mapping for the SupplierID column of Products to ComboBox
- Set the control mapping of other columns you don’t want to display to None.
- Drag and drop the Products table onto a form. A binding source, binding navigator, the textboxes and the combobox will be generated with their labels.
- Select the ComboBox in the designer.
- Go to the Properties grid and select the (DataBindings) property (Advanced) subproperty. Select the ellipses (…) to get the dialog up.
- The Text property will have a Binding set up for it. Remove that by selecting the Binding drop down and selecting None at the top of the list.
- Select the SelectedValue property in the Advanced Bindings window and select the productsBindingSource.SupplierID as the bound column. OK out of there.
- Go back to the Data Sources window and drag the Suppliers table onto the ComboBox. This will hook up the DataSource, DisplayMember, and ValueMember properties.
Hope that is helpful to those groping around with similar data binding scenarios out there.