WinForms:DataGridView - 编辑单元格时显示组合框
WinForms: DataGridView - Show Combobox when cell being Edit
在 C# 应用程序中,我有一个 DatagridView,其中所有单元格都作为 DataGridTextBoxCol。网格由未绑定的值动态填充。网格有不同类型的食物。
我的需要是,当用户 clicks/wants 编辑一个单元格时 - 一个带有食品列表的组合框出现在单元格的位置。如果它们是单元格中的任何值,则应在组合中选择该值。用户可以键入并在组合中选择项目。
这是我到目前为止尝试过的:
private void PopulateAllergensCombo()
{
// Populate Combo box in Form_load & be hidden
BindingSource allergensBindSource = new BindingSource();
allergensList = dbOperations.GetAllergensListObjects();
allergensBindSource.DataSource = allergensList;
allergensCmb.DataSource = allergensBindSource.DataSource; // allergensList;
allergensCmb.DisplayMember = "Name";
allergensCmb.ValueMember = "AllergensNumber";
}
将此组合 allergensCmb
放入当前单元格
private void cellAssignments_dgv_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
DataGridViewCell dvCell = cellAssignments_dgv.CurrentCell;
allergensCmb.Location = dvCell.ContentBounds.Location; // location of cell is X=0, Y=11 - This seems to be relevant from grid & not from Form
if ( String.IsNullOrEmpty(cellAssignments_dgv.CurrentCell.Value.ToString()) == false )
allergensCmb.SelectedValue = cellAssignments_dgv.CurrentCell.Value;
allergensCmb.Show();
}
与上述 dgv_CellBeginEdit
事件代码一样,组合不会显示在单元格位置中。单元格的位置是 X=0,Y=11 - 第一列第一行单元格。它与表单尺寸无关。
为了获取和设置从网格单元格中的组合中选择的项目的值,我尝试实现 CellEndEdit 和 allergensCmb_SelectedIndexChanged 事件。但是没有什么是 100% 的。使用 selectedIndexChanged 事件,我丢失了当前单元格,因为单元格不再处于活动状态;无法获取当前单元格或者它是否脏了!!
任何线索,我如何实现这种类型的控件 - 在 DataGridView 的当前单元格上显示一个组合框。我做了很多研究并进行了尝试,但没有达到预期的效果。
非常感谢任何帮助。
////////////////////////////////////////
************ 更新
////////////////////////////////////////////////
正如你们都建议使用 DataGridViewComboBoxColumn,我做了:
// Add Columns
for (int i = 1; i <= pair.Value.CellBodyRowData.Count; i++)
{
DataGridViewComboBoxColumn cbCol = new DataGridViewComboBoxColumn();
cbCol.HeaderText = i.ToString();
cbCol.Name = i.ToString();
cbCol.DataSource = allergensList;
cbCol.ValueMember = "AllergensNumber";
cbCol.DisplayMember = "Name";
cellAssignments_dgv.Columns.Add(cbCol);
// *** cellAssignments_dgv.Columns.Add((i.ToString(), i.ToString());
}
// Populate in each Row
foreach (CellBodyRowData cbrData in cbRow.CellBodyRowData)
{
// ***** dgvr.Cells[cbrData.Col - 1].Value = cbrData.CellAllergen.Name;
if (cbrData.CellAllergen.AllergensNumber > 0)
dgvr.Cells[cbrData.Col - 1].Value = cbrData.CellAllergen.AllergensNumber;
else
dgvr.Cells[cbrData.Col - 1].Value = 0;
}
这很好。在网格中,我只将每个单元格视为 ComboBox。如何使其仅显示为普通文本,并且仅在编辑时显示为组合框。使用 EditingControlShowing 事件的原因是什么——我不明白这个逻辑??我只需要更改值并将标志 isCellAssignGridChanged
设置为 true,这样就可以更新数据库了。
你能对这部分有所了解吗?
谢谢
感谢@Plutonix 和@JohnKane。
- 我将网格中的列更改为
DataGridViewComboBoxColumn
。
- 更改列的
DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
。
实施了 EditingControlShowing
事件并更改了组合框的下拉样式 cb.DropDownStyle = ComboBoxStyle.DropDownList;
& SelectionChangeCommitted
private void cellAssignments_dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (e.Control is ComboBox)
{
ComboBox cb = (ComboBox)e.Control;
if (cb != null)
{
// Show the DropDown of the combo & set its event
cb.DropDownStyle = ComboBoxStyle.DropDownList;
cb.SelectionChangeCommitted -= cb_SelectionChangeCommitted;
cb.SelectionChangeCommitted += cb_SelectionChangeCommitted;
}
}
}
void cb_SelectionChangeCommitted(object sender, EventArgs e)
{
ComboBox cb = (ComboBox)sender;
if (cb != null)
{
Console.WriteLine("Selected Combo = " + cb.SelectedText + " Value = " + cb.SelectedValue);
// Notify the cell is dirty
cellAssignments_dgv.NotifyCurrentCellDirty(true);
// Force to End Edit the Cell
cellAssignments_dgv.EndEdit();
}
}
- 最后,在
CellEndEdit
事件中,实现了我的update更新集合对象
希望这对某些人有所帮助。
此致,
在 C# 应用程序中,我有一个 DatagridView,其中所有单元格都作为 DataGridTextBoxCol。网格由未绑定的值动态填充。网格有不同类型的食物。 我的需要是,当用户 clicks/wants 编辑一个单元格时 - 一个带有食品列表的组合框出现在单元格的位置。如果它们是单元格中的任何值,则应在组合中选择该值。用户可以键入并在组合中选择项目。 这是我到目前为止尝试过的:
private void PopulateAllergensCombo()
{
// Populate Combo box in Form_load & be hidden
BindingSource allergensBindSource = new BindingSource();
allergensList = dbOperations.GetAllergensListObjects();
allergensBindSource.DataSource = allergensList;
allergensCmb.DataSource = allergensBindSource.DataSource; // allergensList;
allergensCmb.DisplayMember = "Name";
allergensCmb.ValueMember = "AllergensNumber";
}
将此组合 allergensCmb
放入当前单元格
private void cellAssignments_dgv_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
DataGridViewCell dvCell = cellAssignments_dgv.CurrentCell;
allergensCmb.Location = dvCell.ContentBounds.Location; // location of cell is X=0, Y=11 - This seems to be relevant from grid & not from Form
if ( String.IsNullOrEmpty(cellAssignments_dgv.CurrentCell.Value.ToString()) == false )
allergensCmb.SelectedValue = cellAssignments_dgv.CurrentCell.Value;
allergensCmb.Show();
}
与上述 dgv_CellBeginEdit
事件代码一样,组合不会显示在单元格位置中。单元格的位置是 X=0,Y=11 - 第一列第一行单元格。它与表单尺寸无关。
为了获取和设置从网格单元格中的组合中选择的项目的值,我尝试实现 CellEndEdit 和 allergensCmb_SelectedIndexChanged 事件。但是没有什么是 100% 的。使用 selectedIndexChanged 事件,我丢失了当前单元格,因为单元格不再处于活动状态;无法获取当前单元格或者它是否脏了!!
任何线索,我如何实现这种类型的控件 - 在 DataGridView 的当前单元格上显示一个组合框。我做了很多研究并进行了尝试,但没有达到预期的效果。
非常感谢任何帮助。
//////////////////////////////////////// ************ 更新 ////////////////////////////////////////////////
正如你们都建议使用 DataGridViewComboBoxColumn,我做了:
// Add Columns
for (int i = 1; i <= pair.Value.CellBodyRowData.Count; i++)
{
DataGridViewComboBoxColumn cbCol = new DataGridViewComboBoxColumn();
cbCol.HeaderText = i.ToString();
cbCol.Name = i.ToString();
cbCol.DataSource = allergensList;
cbCol.ValueMember = "AllergensNumber";
cbCol.DisplayMember = "Name";
cellAssignments_dgv.Columns.Add(cbCol);
// *** cellAssignments_dgv.Columns.Add((i.ToString(), i.ToString());
}
// Populate in each Row
foreach (CellBodyRowData cbrData in cbRow.CellBodyRowData)
{
// ***** dgvr.Cells[cbrData.Col - 1].Value = cbrData.CellAllergen.Name;
if (cbrData.CellAllergen.AllergensNumber > 0)
dgvr.Cells[cbrData.Col - 1].Value = cbrData.CellAllergen.AllergensNumber;
else
dgvr.Cells[cbrData.Col - 1].Value = 0;
}
这很好。在网格中,我只将每个单元格视为 ComboBox。如何使其仅显示为普通文本,并且仅在编辑时显示为组合框。使用 EditingControlShowing 事件的原因是什么——我不明白这个逻辑??我只需要更改值并将标志 isCellAssignGridChanged
设置为 true,这样就可以更新数据库了。
你能对这部分有所了解吗?
谢谢
感谢@Plutonix 和@JohnKane。
- 我将网格中的列更改为
DataGridViewComboBoxColumn
。 - 更改列的
DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
。 实施了
EditingControlShowing
事件并更改了组合框的下拉样式cb.DropDownStyle = ComboBoxStyle.DropDownList;
& SelectionChangeCommittedprivate void cellAssignments_dgv_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { if (e.Control is ComboBox) { ComboBox cb = (ComboBox)e.Control; if (cb != null) { // Show the DropDown of the combo & set its event cb.DropDownStyle = ComboBoxStyle.DropDownList; cb.SelectionChangeCommitted -= cb_SelectionChangeCommitted; cb.SelectionChangeCommitted += cb_SelectionChangeCommitted; } } } void cb_SelectionChangeCommitted(object sender, EventArgs e) { ComboBox cb = (ComboBox)sender; if (cb != null) { Console.WriteLine("Selected Combo = " + cb.SelectedText + " Value = " + cb.SelectedValue); // Notify the cell is dirty cellAssignments_dgv.NotifyCurrentCellDirty(true); // Force to End Edit the Cell cellAssignments_dgv.EndEdit(); } }
- 最后,在
CellEndEdit
事件中,实现了我的update更新集合对象
希望这对某些人有所帮助。
此致,