Datagridview 中的州、县和市级联组合框列
Posted
技术标签:
【中文标题】Datagridview 中的州、县和市级联组合框列【英文标题】:State, County, and City cascading comboboxcolumns in Datagridview 【发布时间】:2013-07-25 17:42:42 【问题描述】:州、县和市级联组合框列。 我刚刚创建了一个带有 datagridview 的简单表单。 datagridview 包含 3 个组合框列(州、县和市)。当您选择一个州时,县组合框应仅显示该州内的县,当您选择县时,城市列应仅显示所选州和县内的城市。我需要能够随时更改州和县,这应该重置其他相应的列。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StateCountyCityDataGridViewComboboxColumnIssue
public partial class Form1 : Form
private DataTable dtStateCountyCity = new DataTable();
public Form1()
InitializeComponent();
dtStateCountyCity = CreateDataTable_StateCountyCity();
var stateList = (from scc in dtStateCountyCity.AsEnumerable()
group scc by scc.Field<string>("state") into g
select new State = g.Key ).ToList();
dgvCmbColState.DataSource = stateList;
dgvCmbColState.DisplayMember = "state";
dgvCmbColState.ValueMember = "state";
public DataTable CreateDataTable_StateCountyCity()
DataTable dt = new DataTable();
dt.Columns.Add("State", typeof(string));
dt.Columns.Add("County", typeof(string));
dt.Columns.Add("City", typeof(string));
dt.Rows.Add("Michigan", "Oakland", "Royal Oak");
dt.Rows.Add("Michigan", "Oakland", "Birmingham");
dt.Rows.Add("Michigan", "Oakland", "Troy");
dt.Rows.Add("Michigan", "Macomb", "Sterling Heights");
dt.Rows.Add("Michigan", "Macomb", "Warren");
dt.Rows.Add("Illinois", "Cook", "Chicago");
dt.Rows.Add("Illinois", "Cook", "Alsip");
dt.Rows.Add("Illinois", "Cook", "Oak Park");
dt.Rows.Add("Illinois", "Clinton", "Albers");
dt.Rows.Add("Illinois", "Clinton", "Aviston");
return dt;
private void CountyComboBox_DropDown(object sender, EventArgs e)
//Int64 xRefID = Convert.ToInt64(dgvDepartmentWorkersComp.CurrentRow.Cells[6].Value);
if (dgvStateCountyCity.CurrentRow.Cells[0].Value != null)
string stateSelected = dgvStateCountyCity.CurrentRow.Cells[0].Value.ToString();
DataRow[] drTempRows = dtStateCountyCity.Select("State = '" + stateSelected + "'");
if (drTempRows != null && drTempRows.Length > 0)
DataTable dtTemp = drTempRows.CopyToDataTable();
var countyList = (from tblCounty in dtTemp.AsEnumerable()
group tblCounty by tblCounty.Field<string>("county") into g
select new County = g.Key ).ToList();
BindingSource bs = new BindingSource(countyList, "");
dgvCmbColCounty.DataSource = bs;
dgvCmbColCounty.DisplayMember = "County";
dgvCmbColCounty.ValueMember = "County";
private void CityComboBox_DropDown(object sender, EventArgs e)
//Int64 xRefID = Convert.ToInt64(dgvDepartmentWorkersComp.CurrentRow.Cells[6].Value);
if (dgvStateCountyCity.CurrentRow.Cells[1].Value != null)
string countySelected = dgvStateCountyCity.CurrentRow.Cells[1].Value.ToString();
DataRow[] drTempRows = dtStateCountyCity.Select("County = '" + countySelected + "'");
if (drTempRows != null && drTempRows.Length > 0)
DataTable dtTemp = drTempRows.CopyToDataTable();
BindingSource bs = new BindingSource(dtTemp, "");
dgvCmbColCity.DataSource = bs;
dgvCmbColCity.DisplayMember = "City";
dgvCmbColCity.ValueMember = "City";
private void StateSelectionChanged(object sender, EventArgs e)
private void dgvStateCountyCity_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
int stateColumnIndex = 0;
int countyColumnIndex = 1;
int cityColumnIndex = 2;
if (e.Control is ComboBox)
if (dgvStateCountyCity.CurrentCell.ColumnIndex == countyColumnIndex)
ComboBox CountyComboBox = e.Control as ComboBox;
if (CountyComboBox != null)
CountyComboBox.DropDown += new EventHandler(CountyComboBox_DropDown);
if (dgvStateCountyCity.CurrentCell.ColumnIndex == cityColumnIndex)
ComboBox CityComboBox = e.Control as ComboBox;
if (CityComboBox != null)
CityComboBox.DropDown += new EventHandler(CityComboBox_DropDown);
//register selectedvaluechanged event and reset item combobox to default if category changes
if (dgvStateCountyCity.CurrentCell != null && dgvStateCountyCity.CurrentCell.ColumnIndex == stateColumnIndex)
ComboBox StateComboBox = e.Control as ComboBox;
if (StateComboBox != null)
StateComboBox.SelectedValueChanged += new EventHandler(StateSelectionChanged);
//Because filtering this way can make some cell have a value which is not contained in
//the DataGridViewComboBoxColumn.Items, we have to handle the DataError
private void dgvStateCountyCity_DataError(object sender, DataGridViewDataErrorEventArgs e)
//We're interested only in DataGridViewComboBoxColumn
if (dgvStateCountyCity.Columns[e.ColumnIndex] is DataGridViewComboBoxColumn)
e.Cancel = true;
关于由谁完成此任务的任何想法?非常感谢您的帮助!
【问题讨论】:
DataGridView Cascading/Dependent ComboBox Columns 【参考方案1】:我发现答案隐藏在其他地方。所以我修复了我的代码,就在这里。关键是你必须使用DataGridViewComboBoxCell。这是一个完整的工作示例。随意使用,无需任何保证。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace StateCountyCityDataGridViewComboboxColumnIssue
public partial class Form1 : Form
private DataTable dtStateCountyCity = new DataTable();
public Form1()
InitializeComponent();
dtStateCountyCity = CreateDataTable_StateCountyCity();
var stateList = (from scc in dtStateCountyCity.AsEnumerable()
group scc by scc.Field<string>("state") into g
select new State = g.Key ).ToList();
dgvCmbColState.DataSource = stateList;
dgvCmbColState.DisplayMember = "state";
dgvCmbColState.ValueMember = "state";
public DataTable CreateDataTable_StateCountyCity()
DataTable dt = new DataTable();
dt.Columns.Add("State", typeof(string));
dt.Columns.Add("County", typeof(string));
dt.Columns.Add("City", typeof(string));
dt.Rows.Add("Michigan", "Oakland", "Royal Oak");
dt.Rows.Add("Michigan", "Oakland", "Birmingham");
dt.Rows.Add("Michigan", "Oakland", "Troy");
dt.Rows.Add("Michigan", "Macomb", "Sterling Heights");
dt.Rows.Add("Michigan", "Macomb", "Warren");
dt.Rows.Add("Illinois", "Cook", "Chicago");
dt.Rows.Add("Illinois", "Cook", "Alsip");
dt.Rows.Add("Illinois", "Cook", "Oak Park");
dt.Rows.Add("Illinois", "Clinton", "Albers");
dt.Rows.Add("Illinois", "Clinton", "Aviston");
return dt;
//Because filtering this way can make some cell have a value which is not contained in
//the DataGridViewComboBoxColumn.Items, we have to handle the DataError
private void dgvStateCountyCity_DataError(object sender, DataGridViewDataErrorEventArgs e)
//We're interested only in DataGridViewComboBoxColumn
if (dgvStateCountyCity.Columns[e.ColumnIndex] is DataGridViewComboBoxColumn)
e.Cancel = true;
private void dgvStateCountyCity_CellClick(object sender, DataGridViewCellEventArgs e)
if (e.ColumnIndex == 1)
if (dgvStateCountyCity.CurrentRow.Cells[0].Value != null)
string stateSelected = dgvStateCountyCity.CurrentRow.Cells[0].Value.ToString();
DataRow[] drTempRows = dtStateCountyCity.Select("State = '" + stateSelected + "'");
if (drTempRows != null && drTempRows.Length > 0)
DataTable dtTemp = drTempRows.CopyToDataTable();
var countyList = (from tblCounty in dtTemp.AsEnumerable()
group tblCounty by tblCounty.Field<string>("county") into g
select new County = g.Key ).ToList();
BindingSource bs = new BindingSource(countyList, "");
// NOTE: Here is what was changed from my previous code
DataGridViewComboBoxCell comboCell = dgvStateCountyCity[1, dgvStateCountyCity.CurrentRow.Index] as DataGridViewComboBoxCell;
comboCell.DataSource = new BindingSource(bs, null);
comboCell.DisplayMember = "County"; //name of column indataTable to display!!
comboCell.ValueMember = "County"; // vlaue if needed
if (e.ColumnIndex == 2)
if (dgvStateCountyCity.CurrentRow.Cells[1].Value != null)
string countySelected = dgvStateCountyCity.CurrentRow.Cells[1].Value.ToString();
DataRow[] drTempRows = dtStateCountyCity.Select("County = '" + countySelected + "'");
if (drTempRows != null && drTempRows.Length > 0)
DataTable dtTemp = drTempRows.CopyToDataTable();
BindingSource bs = new BindingSource(dtTemp, "");
// NOTE: Here is what was changed from my previous code
DataGridViewComboBoxCell comboCell2 = dgvStateCountyCity[2, dgvStateCountyCity.CurrentRow.Index] as DataGridViewComboBoxCell;
comboCell2.DataSource = new BindingSource(bs, null);
comboCell2.DisplayMember = "City"; //name of column indataTable to display!!
comboCell2.ValueMember = "City"; // vlaue if needed
private void dgvStateCountyCity_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
//Register SelectedValueChanged event and reset item comboBox to default if category changes
if (dgvStateCountyCity.CurrentCell.ColumnIndex == 0 )
ComboBox comboBox = e.Control as ComboBox;
comboBox.SelectedIndexChanged -= new EventHandler(dgvcbState_SelectedValueChanged);
comboBox.SelectedIndexChanged += new EventHandler(dgvcbState_SelectedValueChanged);
private void dgvcbState_SelectedValueChanged(object sender, EventArgs e)
//If category value changed then reset item to default.
if (dgvStateCountyCity.CurrentCell.ColumnIndex == 0)
if (((DataGridViewComboBoxEditingControl)sender).EditingControlValueChanged == true)
dgvStateCountyCity.CurrentRow.Cells[1].Value = "";
dgvStateCountyCity.CurrentRow.Cells[2].Value = "";
【讨论】:
以上是关于Datagridview 中的州、县和市级联组合框列的主要内容,如果未能解决你的问题,请参考以下文章