C# 如何根据第一个GridViewComboxColumn的选择填充第二列

C# 如何根据第一个GridViewComboxColumn的选择填充第二列,c#,winforms,c#-4.0,datagridview,datagridviewcombobox,C#,Winforms,C# 4.0,Datagridview,Datagridviewcombobox,我有两个DataGridViewComboxColumn。我想根据第一个GridViewComboBoxColumn的选择填充第二列。我在第一个Combobox中有组,在第二个ComboxColumn中有服务。我希望当我选择group1时,只有group1的服务显示在服务组合框中。 我正在使用存储过程 var groupColumn = new DataGridViewComboBoxColumn(); DataTable dtcategori = cb.Get

我有两个DataGridViewComboxColumn。我想根据第一个GridViewComboBoxColumn的选择填充第二列。我在第一个Combobox中有组,在第二个ComboxColumn中有服务。我希望当我选择group1时,只有group1的服务显示在服务组合框中。 我正在使用存储过程

var groupColumn = new DataGridViewComboBoxColumn();

                DataTable dtcategori = cb.GetAllDataCategori();
                groupColumn.Name = "Group";
                groupColumn.HeaderText = Resources.GroupName;
                groupColumn.DataSource = dtcategori;
                groupColumn.ValueMember = "ID";
                groupColumn.DisplayMember = "Name";
                groupColumn.Width = 100;
                this.DataGridViewFactor.Columns.Add(groupColumn);

                var serviceColumn = new DataGridViewComboBoxColumn();
                    //var categoriId = Convert.ToInt32(groupColumn.);
                // DataTable dtServices = sb.ServiceGetById(categoriId);
                    DataTable dtServices = sb.GetAllDataServices();
                    serviceColumn.Name = "Services";
                    serviceColumn.HeaderText = Resources.Service;
                    serviceColumn.DataSource = dtServices;
                    serviceColumn.ValueMember = "ID";
                    serviceColumn.DisplayMember = "Name";
                    serviceColumn.Width = 100;

                    this.DataGridViewFactor.Columns.Add(serviceColumn);

哇,我花了大约2个小时才找到这个答案,虽然不是很好,但很有用:)

首先,您必须将
groupColumn.DataSource
更改为
BindingSource
而不是代码中的
DataTable
,因为当您从
groupColumn
中的组合框中选择项目时,需要一些
PositionChanged
事件来通知。您知道,
DataGridViewColumn
没有任何
SelectedIndexChanged
事件。其次,我看不到您的
服务
之间有任何关系,
服务
的数据源应该有一个类似
组ID
的字段,以便您可以在两列之间链接。我想有这样一个
GroupID
字段。您的
Services
有一个
ID
,但我不确定它是否是
GroupID
,它可能是您的
ServiceID

推荐:我认为您应该将
groupColumn的
serviceColumn的
DisplayStyle
更改为
DataGridViewComboBoxDisplayStyle。没有任何内容
-我觉得最合适

我想在代码旁边的注释中解释我的解决方案。代码如下:

//Your code is modified a little.
var groupColumn = new DataGridViewComboBoxColumn();
groupColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
DataTable dtcategori = cb.GetAllDataCategori();
groupColumn.Name = "Group";
groupColumn.HeaderText = Resources.GroupName;
//Create a BindingSource from your DataTable
BindingSource bs = new BindingSource(dtcategori,"");
groupColumn.DataSource = bs;
bs.PositionChanged += (s,e) => {
   //Filter for items which have the selected GroupID
   ((DataTable)((DataGridViewComboBoxColumn)DataGridViewFactor.Columns["Services"]).DataSource).DefaultView.RowFilter =
                string.Format("GroupID='{0}'",((DataRowView)bs.Current).Row["ID"]);
   //Set the initial value of the corresponding cell in serviceColumn
   DataGridViewFactor.CurrentRow.Cells["Services"].Value = ((DataTable)((DataGridViewComboBoxColumn)DataGridViewFactor.Columns["Services"]).DataSource).DefaultView.ToTable().Rows[0]["Name"];
};
//-------------------------------------------
groupColumn.ValueMember = "ID";
groupColumn.DisplayMember = "Name";
groupColumn.Width = 100;
this.DataGridViewFactor.Columns.Add(groupColumn);

var serviceColumn = new DataGridViewComboBoxColumn();
serviceColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
//var categoriId = Convert.ToInt32(groupColumn.);
// DataTable dtServices = sb.ServiceGetById(categoriId);
DataTable dtServices = sb.GetAllDataServices();
serviceColumn.Name = "Services";
serviceColumn.HeaderText = Resources.Service;
serviceColumn.DataSource = dtServices;
serviceColumn.ValueMember = "ID";
serviceColumn.DisplayMember = "Name";
serviceColumn.Width = 100;

this.DataGridViewFactor.Columns.Add(serviceColumn);

//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 DataGridViewFactor_DataError(object sender, DataGridViewDataErrorEventArgs e){
    //We're interested only in DataGridViewComboBoxColumn
    if(DataGridViewFactor.Columns[e.ColumnIndex] is DataGridViewComboBoxColumn){
        e.Cancel = true;
    }
}
//Because when you filter on a row, the DataGridViewComboBoxColumn.DataSource with
//the filtered DefaultView will apply on all the rows in the same 
//DataGridViewComboBoxColumn, we have to apply the filter for each row if it is selected
private void DataGridViewFactor_SelectionChanged(object sender, EventArgs e)
{            
        ((DataTable)((DataGridViewComboBoxColumn)DataGridViewFactor.Columns["Services"]).DataSource).DefaultView.RowFilter =
           string.Format("GroupID='{0}'", DataGridViewFactor.CurrentRow.Cells["Group"].Value);            
}
//Because when you filter on a row, the DataSource DefaultView of the groupColumn will
//be changed (limited to fewer items) and there will be cells in that column having 
//values which are not contained in the filtered items. Those cells will not be 
//displayed when you move the mouse over. This CellPainting event handler is to help 
//them look normal.
private void DataGridViewFactor_CellPainting(object sender, DataGridViewCellPaintingEventArgs e){
    if (e.RowIndex > -1 && e.ColumnIndex > -1)
    {
            if (e.Value != null)
            {
                e.Handled = true;
                e.PaintBackground(e.CellBounds, true);
                StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Center };
                e.Graphics.DrawString(e.Value.ToString(), DataGridViewFactor.Font, new SolidBrush(DataGridViewFactor.ForeColor), e.CellBounds, sf);
            }
    }
}
就这些


我希望它能帮助你

哇,我花了大约2个小时才找到这个答案,虽然不是很好,但很有用:)

首先,您必须将
groupColumn.DataSource
更改为
BindingSource
而不是代码中的
DataTable
,因为当您从
groupColumn
中的组合框中选择项目时,需要一些
PositionChanged
事件来通知。您知道,
DataGridViewColumn
没有任何
SelectedIndexChanged
事件。其次,我看不到您的
服务
之间有任何关系,
服务
的数据源应该有一个类似
组ID
的字段,以便您可以在两列之间链接。我想有这样一个
GroupID
字段。您的
Services
有一个
ID
,但我不确定它是否是
GroupID
,它可能是您的
ServiceID

推荐:我认为您应该将
groupColumn的
serviceColumn的
DisplayStyle
更改为
DataGridViewComboBoxDisplayStyle。没有任何内容
-我觉得最合适

我想在代码旁边的注释中解释我的解决方案。代码如下:

//Your code is modified a little.
var groupColumn = new DataGridViewComboBoxColumn();
groupColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
DataTable dtcategori = cb.GetAllDataCategori();
groupColumn.Name = "Group";
groupColumn.HeaderText = Resources.GroupName;
//Create a BindingSource from your DataTable
BindingSource bs = new BindingSource(dtcategori,"");
groupColumn.DataSource = bs;
bs.PositionChanged += (s,e) => {
   //Filter for items which have the selected GroupID
   ((DataTable)((DataGridViewComboBoxColumn)DataGridViewFactor.Columns["Services"]).DataSource).DefaultView.RowFilter =
                string.Format("GroupID='{0}'",((DataRowView)bs.Current).Row["ID"]);
   //Set the initial value of the corresponding cell in serviceColumn
   DataGridViewFactor.CurrentRow.Cells["Services"].Value = ((DataTable)((DataGridViewComboBoxColumn)DataGridViewFactor.Columns["Services"]).DataSource).DefaultView.ToTable().Rows[0]["Name"];
};
//-------------------------------------------
groupColumn.ValueMember = "ID";
groupColumn.DisplayMember = "Name";
groupColumn.Width = 100;
this.DataGridViewFactor.Columns.Add(groupColumn);

var serviceColumn = new DataGridViewComboBoxColumn();
serviceColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
//var categoriId = Convert.ToInt32(groupColumn.);
// DataTable dtServices = sb.ServiceGetById(categoriId);
DataTable dtServices = sb.GetAllDataServices();
serviceColumn.Name = "Services";
serviceColumn.HeaderText = Resources.Service;
serviceColumn.DataSource = dtServices;
serviceColumn.ValueMember = "ID";
serviceColumn.DisplayMember = "Name";
serviceColumn.Width = 100;

this.DataGridViewFactor.Columns.Add(serviceColumn);

//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 DataGridViewFactor_DataError(object sender, DataGridViewDataErrorEventArgs e){
    //We're interested only in DataGridViewComboBoxColumn
    if(DataGridViewFactor.Columns[e.ColumnIndex] is DataGridViewComboBoxColumn){
        e.Cancel = true;
    }
}
//Because when you filter on a row, the DataGridViewComboBoxColumn.DataSource with
//the filtered DefaultView will apply on all the rows in the same 
//DataGridViewComboBoxColumn, we have to apply the filter for each row if it is selected
private void DataGridViewFactor_SelectionChanged(object sender, EventArgs e)
{            
        ((DataTable)((DataGridViewComboBoxColumn)DataGridViewFactor.Columns["Services"]).DataSource).DefaultView.RowFilter =
           string.Format("GroupID='{0}'", DataGridViewFactor.CurrentRow.Cells["Group"].Value);            
}
//Because when you filter on a row, the DataSource DefaultView of the groupColumn will
//be changed (limited to fewer items) and there will be cells in that column having 
//values which are not contained in the filtered items. Those cells will not be 
//displayed when you move the mouse over. This CellPainting event handler is to help 
//them look normal.
private void DataGridViewFactor_CellPainting(object sender, DataGridViewCellPaintingEventArgs e){
    if (e.RowIndex > -1 && e.ColumnIndex > -1)
    {
            if (e.Value != null)
            {
                e.Handled = true;
                e.PaintBackground(e.CellBounds, true);
                StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Center };
                e.Graphics.DrawString(e.Value.ToString(), DataGridViewFactor.Font, new SolidBrush(DataGridViewFactor.ForeColor), e.CellBounds, sf);
            }
    }
}
就这些


我希望它能帮助你

您的要求似乎很正常,但有一种情况使其不稳定:当您将DataGridViewComboBoxColumn数据源绑定到DataTable时,每行中的所有ComboxColumn都将使用相同的数据源,假设此数据源有4项:1,2,3,4。如果从Column1中选择,并使数据源仅保留1,2,但其他行的Column2中有值为3和4的单元格,该怎么办?这些单元格将不显示。您知道
组合框的工作原理,如果该值不在其
项目列表中,则不会显示该值。这就是为什么我尝试解决这个问题,但并不容易。您的要求似乎很正常,但有一种情况使其不稳定:当您将DataGridViewComboxColumn数据源绑定到DataTable时,每行中的所有ComboxColumn都将使用相同的数据源,假设此数据源有4项:1、2、3、4。如果从Column1中选择,并使数据源仅保留1,2,但其他行的Column2中有值为3和4的单元格,该怎么办?这些单元格将不显示。您知道
组合框的工作原理,如果该值不在其
项目列表中,则不会显示该值。这就是为什么我试图解决这个问题,但并不容易。