A common scenario when entering data is a cascade of comboboxes, where the list in the next combo is populated after selecting a value in the previous.

A typical example is selecting a country from a combo then selecting from a filtered list of cities in a second combo.

We have had tons of questions on how this can be done within a row in RadGridVIew so I decided to make a small demo. I have used a nice List of countries by continent.







There are lots of ways to achieve this with RadGirdView. Bellow I have tried to demonstrate the most-descent-in-my-opinion way  :).

As always I should mention that despite the demo uses RadGridVIew for Silverlight the same technique is applicable for RadGridView for WPF as they both share a common API.


This time I will dive a bit deeper into the steps required to achieve such behavior. If you just need the sample project please scroll over to the end.


1. Bind correctly to data  - the RadGridView and both GridViewComboBoxColumns .

To keep the demo simple I have dumped this  List of countries by continent into the ugly Locations.cs data holder class. (you may download all the files from the link provided at the end)


We bind RadGridView to a List of Location objects.


public class Location
 public string ContinentCode { get; set; }
 public int? CountryID { get; set; }
 public List<Country> AvailableCountries { get; set; }

*Please note this is a simplified version of the Location class. In the downloadable sample bellow the class implements the INotifyPropertyChanged interface. We need this to ensure immediate updates to the UI when the user makes selection in the combo.


Each Location object is associated with a Continent and a Country.

 public class Continent
 public string Code { get; set; }
 public string Name { get; set; }
 public class Country
 public int ID { get; set; }
 public string Name { get; set; }
 public string ContinentCode { get; set; }


We bind the first combo column to a list of continents, and the RadGridView to a list of locations.

((GridViewComboBoxColumn)this.radGridView.Columns[0]).ItemsSource = Locations.Continents;
this.radGridView.ItemsSource = locations;


We bind the second column a bit differently:


<telerik:GridViewComboBoxColumn ItemsSourceBinding="{Binding AvailableCountries}"

Since the items source will be different for each row – different sets of countries for different continents – we use the ItemsSourceBinding property. The AvailableCountries property of the Location object will hold the filtered by continent countries.



2. Provide some filtering logic, so that we can have a list of countries for a selected continent.


 public IEnumerable<Country> AvailableCountries
 return from c in Locations.Countries
                       where c.ContinentCode == this.ContinentCode
                       select c;

3. Ensure the second column reacts immediately on selection changes in the first combo

The default behavior of RadGridView is to commit the newly selected value after the cell loses focus. In our case we need to update the second column immediately after the selected continent has changed.


We subscribe to the RadComboBox.SelectionChangedEvent.

this.AddHandler(RadComboBox.SelectionChangedEvent, new Telerik.Windows.Controls.SelectionChangedEventHandler(comboSelectionChanged));

Within the event handler we update the  underlying business object :

 void comboSelectionChanged(object sender, RadRoutedEventArgs args)
            RadComboBox comboBox = (RadComboBox)args.OriginalSource;
 if (comboBox.SelectedValue==null 
                || comboBox.SelectedValuePath != "Code") // we take action only if the continent combo is changed 
            Location location = comboBox.DataContext as Location;
            location.ContinentCode = (string) comboBox.SelectedValue;//we submit the value immediately rather than waiting the cell to lose focus. 



Please get all the code as well as a working demo project

Related Posts