Skip to main content Skip to footer

How to Assign Different ComboBox Values in Each Row of a WinForms Datagrid

When working with FlexGrid controls, there can be scenarios where we need to change the dropdown items in a cell depending on the selection made in the previous cell, i.e., to have a cascading effect.
This blog post will demonstrate how to populate the cells of a dropdown column with a dynamic set of values in the following situations:

  1. Implementing Cascading Effect in Data Bounded FlexGrid
  1. Implementing Cascading Effect in Unbounded FlexGrid

Ready to Try it Out? Download ComponentOne Today!

Implementing Cascading Effect in Data Bounded FlexGrid

To implement the cascading effect in FlexGrid in bound mode, we will be binding it to the two tiers of the IList data source. As you can see in the GIF below, we are getting a new set of provinces in the dropdown of the second column according to the value in the respective cell of the first column.

For this, let’s first create a custom class named CountryDetails with the property named StateOptions of type List that we will display accordingly in the State cells based on the Country value cell.

public class CountryDetails 
{ 
public string Country { get; set; } 
public string States { get; set; } 
public List StateOptions { get; set; } 
public string Population { get; set; } 
public string Currency { get; set; } 
public CountryDetails() { } 
}}

Create a list of objects of CountryDetails class with some default values and set this collection as the data source of the FlexGrid control.

List<CountryDetails> setupMyBusinessObject()
        {
            List<CountryDetails> mboList = new List<CountryDetails>();
            CountryDetails mbo = new CountryDetails();
            mbo.Country = "Afghanistan";
            mbo.Currency = "Afghan afghani";
            mbo.Population = "30.55 million";
            mbo.States = "Mazar-i-Sharif";
            mbo.StateOptions = new List<string>();
            mbo.StateOptions.Add("Mazar-i-Sharif");
            mbo.StateOptions.Add("Kabul");
            mbo.StateOptions.Add("Kandahar");
            mbo.StateOptions.Add("Herat");
            mbo.StateOptions.Add("Kunduz");
            mboList.Add(mbo);
           //Please refer to the attached sample to see full data
            return (mboList);
        }
  //Assign List of CountryDetails items to the DataSource of FlexGrid
  c1FlexGrid1.DataSource = setupMyBusinessObject();

Across all the rows, you'll find all of the CountryDetails properties filled in (Country, State, Currency, Population). To populate the dropdown in the State column, we will be focused on the StateOptions property of CountryDetails, as said before.

We've prepopulated the cells in the State column with some default values. Still, we've also provided functionality for the user to change the State values by making the Combobox control the Editor of the current State cell and binding the StateOptions list for that row to the Combobox's DataSource.

For this, we are handling the BeforeEdit event of FlexGrid to set the cell editor and its data source.

private void c1FlexGrid1_BeforeEdit(object sender, RowColEventArgs e)  
{  
if (e.Col == 2)  
{  
comboBox1.DataSource = objectList[e.Row - 1].StateOptions;  
c1FlexGrid1.Cols[2].Editor = comboBox1;  
}}  

This way, each State row will display the values concurrent with the corresponding country value.

Implementing Cascading Effect in Unbounded FlexGrid

In some cases, the grid we're dealing with may not be dependent on any data source, yet we still want to have this cascading effect. The GIF below shows how the value in the Job column dropdown menu adapts to the one chosen in the Region column.

Let’s divide this implementation into the following steps:

  • Creation of dropdown data
  • Assign the dropdown in the Job Column based on Region selected

Creation of Dropdown Data

Create the data enumeration for storing the Region and Job values.

enum RegionEnum
{
North, South, East, West
}

enum JobEnum
{
Director, Manager, Accountant, Engineer, Sales, Clerical
}

Create a Hashtable and ListDictionary to define the jobs in each region and to set them as the DataMap for Region and Job column, respectively.

Hashtable _jobsPerRegion;
ListDictionary _mapJobs;
ListDictionary _mapRegions;
//create table to select which jobs exist in each region
_jobsPerRegion = new Hashtable();
_jobsPerRegion.Add(RegionEnum.North, new JobEnum[] { JobEnum.Director, JobEnum.Manager, JobEnum.Accountant, JobEnum.Engineer, JobEnum.Sales, JobEnum.Clerical });
_jobsPerRegion.Add(RegionEnum.South, new JobEnum[] { JobEnum.Manager, JobEnum.Accountant, JobEnum.Sales });
_jobsPerRegion.Add(RegionEnum.East, new JobEnum[] { JobEnum.Manager, JobEnum.Engineer, JobEnum.Clerical });
_jobsPerRegion.Add(RegionEnum.West, new JobEnum[] { JobEnum.Accountant, JobEnum.Sales, JobEnum.Clerical });

//create DataMaps
_mapRegions = new ListDictionary();
foreach (RegionEnum region in Enum.GetValues(typeof(RegionEnum)))
_mapRegions.Add(region, Enum.GetName(typeof(RegionEnum), region));

_mapJobs = new ListDictionary();
foreach (JobEnum job in Enum.GetValues(typeof(JobEnum)))
_mapJobs.Add(job, Enum.GetName(typeof(JobEnum), job));

c1FlexGrid1.Cols[1].DataMap = _mapRegions;
c1FlexGrid1.Cols[1].Name = c1FlexGrid1.Cols[1].Caption = "Region";
c1FlexGrid1.Cols[2].DataMap = _mapJobs;
c1FlexGrid1.Cols[2].Name = c1FlexGrid1.Cols[2].Caption = "Job";

Assign the dropdown in Job Column based on Region Selected

By default, the Job column cells are non-editable which will enable when selecting the region for specific row and to populate the values depending up on the selected region, we will handle the SetupEditor event of FlexGrid and use the ComboBox as the Editor of the Job column with required job values.

private void c1FlexGrid1_SetupEditor(object sender, RowColEventArgs e)
{
// before editing the job, remove items that don't apply to the current region
if (c1FlexGrid1.Cols[e.Col].Name == "Job")
{
ComboBox cb = c1FlexGrid1.Editor as ComboBox;
if (cb != null)
{
// get current region
RegionEnum region = (RegionEnum)c1FlexGrid1[e.Row, "Region"];

// get jobs that exist for this region
JobEnum[] jobs = (JobEnum[])_jobsPerRegion[region];

// populate list with jobs that apply to the current region
cb.Items.Clear();
foreach (JobEnum job in jobs)
{
cb.Items.Add(Enum.GetName(typeof(JobEnum), job));
}}}}

We hope that this demonstration of implementing the cascading effect in the FlexGrid cells while working in bound and unbound modes will make both modes interesting to you.

Download the sample for this blog.

Please try it out and leave your feedback or questions in the comments section. Happy Coding!

Learn more about FlexGrid.

Ready to Try it Out? Download ComponentOne Today!

 

comments powered by Disqus