I was fighting with a pretty simple scenario in a C#.NET Windows Forms project today. I was having trouble getting data binding to behave the way I wanted it to. I'm sure that other people have the same requirements in some of their apps: parent and child combo boxes.
- Bind controls on a form to a dataset called dsAddresses in this example. The parent and child SelectedValue are bound to CountryRegionID and StateProvinceID from this dsAddresses dataset.
- Populate the parent and child combo box items with data from country/region and states/provinces datasources (DataTables in this example) respectively
- When the parent combo box's selected value changes, have the items in the child combo box filtered automatically
Well...I had a solution that was acceptable for the most part, but there was an few issue with the way that I implemented the solution.
Main issue: If you brought up the form and selected an address, the values in the parent and child combo boxes were bound to the correct values, but if you didn't select a country/region (which causes the SelectionChangeCommitted event to fire and this is where I called a method to filter the state/provinces manually in my previous solution) in the parent combo, the states/provinces combo would not be filtered and all states/provinces would show up.
I tried a number of workarounds and was about to scrap the entire original design of the form and start from scratch.
Brad Raulston gave me a hand and we tried a few things and then he researched it and found a blog posting by Andre King:
Parent-Child combo boxes in C#.NET Windows Forms
It detailed a scenario almost exactly like the one outlined above. I can't seem to get to the link at the moment but I was able to get the cached Google version.
Brad graciously helped me with the solution below:
Created a dataset called dsCountryState.
Merged 2 DataTables into it (because I already had them, but will refactor
to fill the dataset with both tables in one shot for efficiency later): one for
the parent Country/Region data and one for the State/Province data.
// Created a DataRelation for the parent and child DataTables like this:
DataRelation rel = new DataRelation("CountryStateRelation", dsCountryState.Tables["CountryRegion"].Columns["CountryRegionID"],
dsCountryState.Tables["StateProvince"].Columns["CountryRegionID"]);
// Accept Changes on the dsCountryState DataSet.
dsCountryState.AcceptChanges();
// parent combo bound to the
"parent_datatable.parent_column"cboCountryRegion.DataSource =
dsCountryState.Tables["CountryRegion"];cboCountryRegion.DisplayMember = "CountryRegion.CountryRegionName";
cboCountryRegion.ValueMember = "CountryRegion.CountryRegionID";
// child combo bound to the "parent_datatable.parent_child_relation.child_column" cboStateProvince.DataSource = dsCountryState;cboStateProvince.DisplayMember = "CountryRegion.CountryStateRelationship.StateProvinceName";
cboStateProvince.ValueMember = "CountryRegion.CountryStateRelationship.StateProvinceID";
What this accomplishes among other things is the combo boxes share
the same BindingManager which enables the required behavior. States/Provinces
are filtered automatically.
Thanks to Brad Raulston and Andre King for
the help and information. Hope this saves you some time and frustration.
No comments:
Post a Comment