2013-07-25 80 views
0

州,縣和城市級聯組合列。 我剛剛創建了一個帶有datagridview的簡單表單。 datagridview contians 3個comboboxcolumns(州,縣和城市)。當您選擇一個州時,縣級組合框只應顯示該州內的縣,當您選擇一個縣時,城市列應只顯示所選州和郡內的城市。我需要能夠隨時更改州和縣,這應該重置其他相應的列。州,縣和城市在Datagridview中級聯組合列

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; 
      } 
     } 

    } 
} 

有關誰來完成此任何想法?非常感謝幫助!

+0

[DataGridView Cascading/Dependent ComboBox Columns](http://stackoverflow.com/a/39487773/3110834) –

回答

0

我發現答案隱藏在別的地方。所以我修復了我的代碼,就在這裏。關鍵是你必須使用DataGridViewComboBoxCell。這是一個完整的工作示例。只要你喜歡和沒有warrenties使用。

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 = ""; 
       } 
      } 

     } 
    } 
}