Cascading ComboBoxes Selection in RadGridView for Silverlight and WPF

Wednesday, January 27, 2010 by Pavel Pavlov | Comments 15

 

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.

 

 

 

cascadingComboboxes

 

 

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:

(XAML)

<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
        {
            get
            {
                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
                return;
            
            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

15 Comments

  • Sunggoo Im 16 Feb 2010

    Pavel,

    This was a great help to me.

    I just started playing with Telerik's Silverlight RadControls and was trying to implement cascading dropdown columns in a Gridview. This demo showed clearly how I should approach the problem.

    Can I, further, ask you for the RIA Service version of this demo?

    I can't get it to integrated with an actual DB.

    Thank you in advance for your consideration,

    Sunggoo.
  • Sunggoo Im 16 Feb 2010

    Pavel,

    This was a great help to me.

    I just started playing with Telerik's Silverlight RadControls and was trying to implement cascading dropdown columns in a Gridview. This demo showed clearly how I should approach the problem.

    Can I, further, ask you for the RIA Service version of this demo?

    I can't get it to integrated with an actual DB.

    Thank you in advance for your consideration,

    Sunggoo.
  • VB 14 Oct 2010

    Hi,

    Can something like this be achieved using MVVM?

  • VB 14 Oct 2010

    Hi,

    Can something like this be achieved using MVVM?

  • Jan Heiko Houtrouw 08 Feb 2011
    Hi,

    The solution works, but the class Location must contain the member AvailableCountries which is just necessary for the user interface. So there is no clean seperation between the user interface and the data objects.

    Not the best solution ...
  • Jan Heiko Houtrouw 08 Feb 2011
    Hi,

    The solution works, but the class Location must contain the member AvailableCountries which is just necessary for the user interface. So there is no clean seperation between the user interface and the data objects.

    Not the best solution ...
  • Jan Heiko Houtrouw 08 Feb 2011
    Hi,

    The solution works, but the class Location must contain the member AvailableCountries which is just necessary for the user interface. So there is no clean seperation between the user interface and the data objects.

    Not the best solution ...
  • f 09 May 2011
    also there are many availablecountries, not a single list that just filteres the countries list.
  • Danny G 08 Jun 2011
    Can this be done with regular RadGridView for WinForms? I'm using RadControls for Windows Forms Q2 2010 and I need the same functionality.
  • Houdini 02 Feb 2012
    My situation is almost like this but not quiet. I am binding my radGridView to a radDomainDataSource, which is pulling from my DomainService class and getting the records of all "Acquisition Status" that comes from the AcquisitionStatus table (via LINQtoSQL model). The AcquisitionStatus has a field called AcquistionTypeID (foreign Key), which points to the AcquisitionType table. All works well until I tried adding a GridViewComboBoxColumn to the radGridView to display the "Types of Acquisition" (a field in my AcquisitionType table) as opposed to displaying the AcquisitionTypeID field. All in all, I want to see the Types (Compulsory, private, etc...) in the box as oppose to seeing 1,2,3...etc.
  • Houdini 02 Feb 2012
    My situation is almost like this but not quiet. I am binding my radGridView to a radDomainDataSource, which is pulling from my DomainService class and getting the records of all "Acquisition Status" that comes from the AcquisitionStatus table (via LINQtoSQL model). The AcquisitionStatus has a field called AcquistionTypeID (foreign Key), which points to the AcquisitionType table. All works well until I tried adding a GridViewComboBoxColumn to the radGridView to display the "Types of Acquisition" (a field in my AcquisitionType table) as opposed to displaying the AcquisitionTypeID field. All in all, I want to see the Types (Compulsory, private, etc...) in the box as oppose to seeing 1,2,3...etc.
  • Johnny 07 Feb 2012
    Hi,
    Thank you for the awesome example. I got a lot from it. I am currently designing a grid that is very similar to the example, however, I have one more column that displays value from the second cascaded combo box. For example, I have third column named population and I would like to use it to display the population from the country selected from the country combo box. I've tried many different approaches but still not sure how to tackle this problem. How can I able to do it? Thanks
  • Johnny 07 Feb 2012
    Hi,
    Thank you for the awesome example. I got a lot from it. I am currently designing a grid that is very similar to the example, however, I have one more column that displays value from the second cascaded combo box. For example, I have third column named population and I would like to use it to display the population from the country selected from the country combo box. I've tried many different approaches but still not sure how to tackle this problem. How can I able to do it? Thanks
  • Johnny 07 Feb 2012
    Hi,
    Thank you for the awesome example. I got a lot from it. I am currently designing a grid that is very similar to the example, however, I have one more column that displays value from the second cascaded combo box. For example, I have third column named population and I would like to use it to display the population from the country selected from the country combo box. I've tried many different approaches but still not sure how to tackle this problem. How can I able to do it? Thanks
  • rduclos 03 Apr 2012
    Do you have an example of this using RIA Services?

Add comment

  1. Formatting options
       
     
     
     
     
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)