In many projects, you may need to create multiple combo-boxes (also known as selection lists) where the next combo box depends on the selection made in the first. When a value is selected in the first box, the next box should show values based on the first selection. For example, you have two combo boxes: one shows car company names (BMW, Mercedes, Ferrari, etc.) and the second shows car types for the selected company (for BMW: 1, 2, 5, X2, X5...; for Mercedes: A, B, C, CL, CLS...).
In order to fill our combo-boxes we need a source where the data should come from. As WPF comes with a native XML engine, we can create an XML file that contains the data. The XML file has the first level content for the first selection. Every entry has child entries for the second selection. These second entries could have even more children in case you need a three level or even more nested selection list. This is how it looks:
Create a data.xml file, copy this content into the file, and save the file near the .xaml file that you want to add cascading combo boxes to (e.g., in C:\ProgramData\Autodesk\Vault 2014\Extensions\DataStandard\Vault\Configuration).
<XmlDataProvider x:Key="comboDataSource" Source="C:\ProgramData\Autodesk\Vault 2014\Extensions\DataStandard\Vault\Configuration\data.xml"/>
<prop:dsWindow.Resources xmlns:prop="clr-namespace:dataStandard.UI.View;assembly=dataStandard.UI"> ... ...... .... <XmlDataProvider x:Key="comboDataSource" Source="C:\ProgramData\Autodesk\Vault 2014\Extensions\DataStandard\Vault\Configuration\data.xml"/> </prop:dsWindow.Resources>
As you can see, we named our new resource as comboDataSource and the path points to our data.xml.
<ComboBox x:Name="ComboCarCompanies" Grid.Column="1" Grid.Row="5" ItemsSource="{Binding Source={StaticResource comboDataSource}, XPath=/Data/Companies/*}" Text="{Binding Prop[CarVendor].Value}" DisplayMemberPath="@Name" SelectedValue="{Binding Prop[CarVendor].Value}" SelectedValuePath="@Name" />
We named the combo ComboCarCompanies and positioned it at column 1, row 5. The source for the content of this combo comes from the resource we named comboDataSource. XPath points to the right path for reading the content. Everything is under the element Companies. The children of the element Companies have one member each called Name. So, the attributes DisplayMemberPath and SelectedValuePath point to @Name. The attributes Text and SelectedValue point to the property that is filled with the value selected by the user.
The second combo looks similar to the first one. The only difference is that the data source comes from the first combo. The user selects one node from the XML file. So that node is now loaded as the selected item in the first combo. The node also knows about the selection's children.
<ComboBox x:Name="ComboCarType" Grid.Column="1" Grid.Row="6" ItemsSource="{Binding SelectedItem, ElementName=ComboCarCompanies}" Text="{Binding Prop[CarType].Value}" DisplayMemberPath="@Type" SelectedValue="{Binding Prop[CarType].Value}" SelectedValuePath="@Type"/>Most attributes in our example play the same role as in the first combo. The real difference is in the ItemSource. This time, we pointed to the SelectedItem from the first combo we earlier called ComboCarCompanies.