C# 如何在DataGridView控件中实现级联组合框?

C# 如何在DataGridView控件中实现级联组合框?,c#,winforms,datagridview,cascadingdropdown,C#,Winforms,Datagridview,Cascadingdropdown,我需要在几个DataGridViews中实现级联组合框。作为概念证明,我将下面的代码放在一起。选择国家时,应填充3列(客户,国家,城市),但不起作用 有没有更好的方法来实现这一点并纠正我做错的事情 public partial class Form1 : Form { private List<Customer> customers; private List<Country> countries; private List<City>

我需要在几个
DataGridView
s中实现级联
组合框。作为概念证明,我将下面的代码放在一起。选择国家时,应填充3列(客户国家城市),但不起作用

有没有更好的方法来实现这一点并纠正我做错的事情

public partial class Form1 : Form
{
    private List<Customer> customers;
    private List<Country> countries;
    private List<City> cities;
    private ComboBox cboCountry;
    private ComboBox cboCity;
    public Form1()
    {
        InitializeComponent();
        countries = GetCountries();
        customers = GetCustomers();

        SetupDataGridView();

    }

    private List<Customer> GetCustomers()
    {
        var customerList = new List<Customer>
                          {
                              new Customer {Id=1,Name = "Jo",Surname = "Smith"},
                              new Customer {Id=2,Name = "Mary",Surname = "Glog"},
                              new Customer {Id=3,Name = "Mark",Surname = "Bloggs"}
                          };

        return customerList;
    }

    private List<Country> GetCountries()
    {
        var countryList = new List<Country>
                          {
                              new Country {Id=1,Name = "England"},
                              new Country {Id=2,Name = "Spain"},
                              new Country {Id=3,Name = "Germany"}
                          };

        return countryList;
    }
    private List<City> GetCities(string countryName)
    {
        var cityList = new List<City>();
        if (countryName == "England") cityList.Add(new City { Id = 1, Name = "London" });
        if (countryName == "Spain") cityList.Add(new City { Id = 2, Name = "Madrid" });
        if (countryName == "Germany") cityList.Add(new City { Id = 3, Name = "Berlin" });

        return cityList;
    }

    private void SetupDataGridView()
    {
        dataGridView1.CellLeave += dataGridView1_CellLeave;
        dataGridView1.EditingControlShowing += dataGridView1_EditingControlShowing;

        DataGridViewTextBoxColumn colCustomer = new DataGridViewTextBoxColumn();
        colCustomer.Name = "colCustomer";
        colCustomer.HeaderText = "CustomerName";

        DataGridViewComboBoxColumn colCountry = new DataGridViewComboBoxColumn();
        colCountry.Name = "colCountry";
        colCountry.HeaderText = "Country";


        DataGridViewComboBoxColumn colCity = new DataGridViewComboBoxColumn();
        colCity.Name = "colCity";
        colCity.HeaderText = "City";


        dataGridView1.Columns.Add(colCustomer);
        dataGridView1.Columns.Add(colCountry);
        dataGridView1.Columns.Add(colCity);


        //Databind gridview columns
        ((DataGridViewComboBoxColumn)dataGridView1.Columns["colCountry"]).DisplayMember = "Name";
        ((DataGridViewComboBoxColumn)dataGridView1.Columns["colCountry"]).ValueMember = "Id";
        ((DataGridViewComboBoxColumn)dataGridView1.Columns["colCountry"]).DataSource = countries;

        ((DataGridViewComboBoxColumn)dataGridView1.Columns["colCity"]).DisplayMember = "Name";
        ((DataGridViewComboBoxColumn)dataGridView1.Columns["colCity"]).ValueMember = "Id";
        ((DataGridViewComboBoxColumn)dataGridView1.Columns["colCity"]).DataSource = cities;

        foreach (Customer cust in customers)
        {
            dataGridView1.Rows.Add(cust.Name + " " + cust.Surname);
        }
    }

    private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
    {
        //register a event to filter displaying value of items column.
        if (dataGridView1.CurrentRow != null && dataGridView1.CurrentCell.ColumnIndex == 2)
        {
            cboCity = e.Control as ComboBox;
            if (cboCity != null)
            {
                cboCity.DropDown += cboCity_DropDown;
            }
        }

        //Register SelectedValueChanged event and reset item comboBox to default if category changes
        if (dataGridView1.CurrentRow != null && dataGridView1.CurrentCell.ColumnIndex == 1)
        {
            cboCountry = e.Control as ComboBox;
            if (cboCountry != null)
            {
                cboCountry.SelectedValueChanged += cboCountry_SelectedValueChanged;
            }
        }
    }

    void cboCountry_SelectedValueChanged(object sender, EventArgs e)
    {
        //If category value changed then reset item to default.
        dataGridView1.CurrentRow.Cells[2].Value = 0;
    }

    void cboCity_DropDown(object sender, EventArgs e)
    {
        string countryName = dataGridView1.CurrentRow.Cells[1].Value.ToString();
        List<City> cities = new List<City>();

        cities = GetCities(countryName);
        cboCity.DataSource = cities;
        cboCity.DisplayMember = "Name";
        cboCity.ValueMember = "Id";


    }

    private void dataGridView1_CellLeave(object sender, DataGridViewCellEventArgs e)
    {
        if (cboCity != null) cboCity.DropDown -= cboCity_DropDown;
        if (cboCountry != null)
        {
            cboCountry.SelectedValueChanged -= cboCountry_SelectedValueChanged;
        }
    }
}

public class Country
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class City
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
}
公共部分类表单1:表单
{
私人名单客户;
私人名单国家;
私人名单城市;
私人组合框CBO国家;
私人组合框社区;
公共表格1()
{
初始化组件();
countries=GetCountries();
customers=GetCustomers();
SetupDataGridView();
}
私有列表GetCustomers()
{
var customerList=新列表
{
新客户{Id=1,Name=“Jo”,Name=“Smith”},
新客户{Id=2,Name=“Mary”,姓氏=“Glog”},
新客户{Id=3,Name=“Mark”,Name=“Bloggs”}
};
返回客户列表;
}
私人名单国家()
{
var countryList=新列表
{
新国家{Id=1,Name=“英格兰”},
新国家{Id=2,Name=“西班牙”},
新国家{Id=3,Name=“德国”}
};
返回国家列表;
}
私有列表GetCities(字符串countryName)
{
var cityList=新列表();
if(countryName==“England”)cityList.Add(新城{Id=1,Name=“伦敦”});
if(countryName==“西班牙”)cityList.Add(新城{Id=2,Name=“马德里”});
if(countryName==“Germany”)cityList.Add(新城市{Id=3,Name=“Berlin”});
返回城市列表;
}
私有void SetupDataGridView()
{
dataGridView1.CellLeave+=dataGridView1_CellLeave;
dataGridView1.EditingControlShowing+=dataGridView1\u EditingControlShowing;
DataGridViewTextBoxColumn colCustomer=新DataGridViewTextBoxColumn();
colCustomer.Name=“colCustomer”;
colCustomer.HeaderText=“CustomerName”;
DataGridViewComboBoxColumn colCountry=新DataGridViewComboxColumn();
colCountry.Name=“colCountry”;
colCountry.HeaderText=“国家”;
DataGridViewComboBoxColumn colCity=新DataGridViewComboxColumn();
colCity.Name=“colCity”;
colCity.HeaderText=“城市”;
dataGridView1.Columns.Add(colCustomer);
dataGridView1.Columns.Add(colCountry);
dataGridView1.Columns.Add(colCity);
//数据绑定gridview列
((DataGridViewComboxColumn)dataGridView1.Columns[“colCountry”]).DisplayMember=“Name”;
((DataGridViewComboxColumn)dataGridView1.Columns[“colCountry”]).ValueMember=“Id”;
((DataGridViewComboxColumn)dataGridView1.Columns[“colCountry”])。数据源=国家;
((DataGridViewComboxColumn)dataGridView1.Columns[“colCity”]).DisplayMember=“Name”;
((DataGridViewComboxColumn)dataGridView1.Columns[“colCity”]).ValueMember=“Id”;
((DataGridViewComboxColumn)dataGridView1.Columns[“colCity”])。数据源=城市;
foreach(客户中的客户)
{
dataGridView1.Rows.Add(cust.Name+“”+cust.姓氏);
}
}
私有void dataGridView1_EditingControlShowing(对象发送方,DataGridViewEditingControlShowingEventArgs e)
{
//注册一个事件以筛选项列的显示值。
如果(dataGridView1.CurrentRow!=null&&dataGridView1.CurrentCell.ColumnIndex==2)
{
cboCity=e.控件作为组合框;
如果(cboCity!=null)
{
cboCity.DropDown+=cboCity\u下拉列表;
}
}
//注册SelectedValueChanged事件,并在类别更改时将项目组合框重置为默认值
if(dataGridView1.CurrentRow!=null&&dataGridView1.CurrentCell.ColumnIndex==1)
{
cbocontry=e.控件作为组合框;
如果(cboCountry!=null)
{
cboCountry.SelectedValueChanged+=cboCountry\u SelectedValueChanged;
}
}
}
void cboCountry\u SelectedValueChanged(对象发送方,事件参数e)
{
//如果类别值更改,则将项目重置为默认值。
dataGridView1.CurrentRow.Cells[2]。值=0;
}
void cboCity_下拉列表(对象发送方、事件参数e)
{
字符串countryName=dataGridView1.CurrentRow.Cells[1].Value.ToString();
列表城市=新列表();
cities=GetCities(countryName);
cboCity.DataSource=城市;
cboCity.DisplayMember=“Name”;
cboCity.ValueMember=“Id”;
}
私有void dataGridView1_CellLeave(对象发送方,DataGridViewCellEventArgs e)
{
if(cboCity!=null)cboCity.DropDown-=cboCity\u DropDown;
如果(cboCountry!=null)
{
cboCountry.SelectedValueChanged-=cboCountry\u SelectedValueChanged;
}
}
}
公营国家
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
公营城市
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}
公共类客户
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串姓氏{get;set;}
}

}

我希望我能简单地用几行代码为您提供一个解决方案,但我可能需要发布一个完整的Visual Studio项目来用代码进行演示

这里的想法是,您不应该试图通过控件的事件来控制此类场景。相反,您应该致力于使用Windows窗体的数据绑定机制。通过将控件绑定到能够
private void Form1_Load(object sender, EventArgs e)
{
    dataGridView1.EditingControlShowing +=new DataGridViewEditingControlShowingEventHandler(dataGridView1_EditingControlShowing);

    DataGridViewComboBoxColumn curCol1 = new DataGridViewComboBoxColumn();
    List<string> source1 = new List<string>() { "val1", "val2", "val3" };
    curCol1.DataSource = source1;
    DataGridViewComboBoxColumn curCol2 = new DataGridViewComboBoxColumn();

    dataGridView1.Columns.Add(curCol1);
    dataGridView1.Columns.Add(curCol2);

    for (int i = 0; i <= 5; i++)
    {
        dataGridView1.Rows.Add();
        dataGridView1[0, i].Value = source1[0];
        changeSourceCol2((string)dataGridView1[0, i].Value, (DataGridViewComboBoxCell)dataGridView1[1, i]);
    }
}

private void changeSourceCol2(string col1Val, DataGridViewComboBoxCell cellToChange)
{
    if (col1Val != null)
    {
        List<string> source2 = new List<string>() { col1Val + "1", col1Val + "2", col1Val + "3" };
        cellToChange.DataSource = source2;
        cellToChange.Value = source2[0];
    }
}

private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
    if (dataGridView1.CurrentRow != null)
    {
        ComboBox col1Combo = e.Control as ComboBox;
        if (col1Combo != null)
        {
            if (dataGridView1.CurrentCell.ColumnIndex == 0)
            {
                col1Combo.SelectedIndexChanged += col1Combo_SelectedIndexChanged;
            }
        }
    }
}

private void col1Combo_SelectedIndexChanged(object sender, EventArgs e)
{
    if (dataGridView1.CurrentCell.ColumnIndex == 0)
    {
        dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
        changeSourceCol2(dataGridView1.CurrentCell.Value.ToString(), (DataGridViewComboBoxCell)dataGridView1[1, dataGridView1.CurrentCell.RowIndex]);
    }
}