C# 如何根据第一个GridViewComboxColumn的选择填充第二列
我有两个DataGridViewComboxColumn。我想根据第一个GridViewComboBoxColumn的选择填充第二列。我在第一个Combobox中有组,在第二个ComboxColumn中有服务。我希望当我选择group1时,只有group1的服务显示在服务组合框中。 我正在使用存储过程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
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的单元格,该怎么办?这些单元格将不显示。您知道组合框的工作原理,如果该值不在其项目列表中,则不会显示该值。这就是为什么我试图解决这个问题,但并不容易。