DataGridViewComboBoxColumn adding different items to each row .
-
01-07-2019 - |
Question
I am building a table using the DataGridView where a user can select items from a dropdown in each cell. To simplify the problem, lets say i have 1 column. I am using the DataGridViewComboBoxColumn in the designer. I am trying to support having each row in that column have a different list of items to choose from.
Is this possible?
Solution
Yes. This can be done using the DataGridViewComboBoxCell.
Here is an example method to add the items to just one cell, rather than the whole column.
private void setCellComboBoxItems(DataGridView dataGrid, int rowIndex, int colIndex, object[] itemsToAdd)
{
DataGridViewComboBoxCell dgvcbc = (DataGridViewComboBoxCell) dataGrid.Rows[rowIndex].Cells[colIndex];
// You might pass a boolean to determine whether to clear or not.
dgvcbc.Items.Clear();
foreach (object itemToAdd in itemsToAdd)
{
dgvcbc.Items.Add(itemToAdd);
}
}
OTHER TIPS
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == DataGridViewComboBoxColumnNumber)
{
setCellComboBoxItems(myDataGridView, e.RowIndex, e.ColumnIndex, someObj);
}
}
Just in case anyone finds this thread, this is my solution in VB 2008. The advantage this offers is that it allows you to assign an ID to each value in the combobox.
Private Sub FillGroups()
Try
'Create Connection and SQLCommand here.
Conn.Open()
Dim dr As SqlDataReader = cm.ExecuteReader
dgvGroups.Rows.Clear()
Dim PreviousGroup As String = ""
Dim l As New List(Of Groups)
While dr.Read
Dim g As New Groups
g.RegionID = CheckInt(dr("cg_id"))
g.RegionName = CheckString(dr("cg_name"))
g.GroupID = CheckInt(dr("vg_id"))
g.GroupName = CheckString(dr("vg_name"))
l.Add(g)
End While
dr.Close()
Conn.Close()
For Each a In (From r In l Select r.RegionName, r.RegionID).Distinct
Dim RegionID As Integer = a.RegionID 'Doing it this way avoids a warning
dgvGroups.Rows.Add(New Object() {a.RegionID, a.RegionName})
Dim c As DataGridViewComboBoxCell = CType(dgvGroups.Rows(dgvGroups.RowCount - 1).Cells(colGroup.Index), DataGridViewComboBoxCell)
c.DataSource = (From g In l Where g.RegionID = RegionID Select g.GroupID, g.GroupName).ToArray
c.DisplayMember = "GroupName"
c.ValueMember = "GroupID"
Next
Catch ex As Exception
End Try
End Sub
Private Class Groups
Private _RegionID As Integer
Public Property RegionID() As Integer
Get
Return _RegionID
End Get
Set(ByVal value As Integer)
_RegionID = value
End Set
End Property
Private _RegionName As String
Public Property RegionName() As String
Get
Return _RegionName
End Get
Set(ByVal value As String)
_RegionName = value
End Set
End Property
Private _GroupName As String
Public Property GroupName() As String
Get
Return _GroupName
End Get
Set(ByVal value As String)
_GroupName = value
End Set
End Property
Private _GroupID As Integer
Public Property GroupID() As Integer
Get
Return _GroupID
End Get
Set(ByVal value As Integer)
_GroupID = value
End Set
End Property
End Class
this is an example with gridView which have 2 comboboxColumns and when a comboBoxColumns1 selected index changed then load comboBoxColumns2 with data from from two different columns from database .
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.Rows[e.RowIndex].Cells[0].Value != null && dataGridView1.CurrentCell.ColumnIndex == 0)
{
SqlConnection conn = new SqlConnection("data source=.;initial catalog=pharmacy;integrated security=true");
SqlCommand cmd = new SqlCommand("select [drugTypeParent],[drugTypeChild] from [drugs] where [drugName]='" + dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString() + "'", conn);
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
object[] o = new object[] { dr[0].ToString(),dr[1].ToString() };
DataGridViewComboBoxCell dgvcbc = (DataGridViewComboBoxCell)dataGridView1.Rows[e.RowIndex].Cells[1];
dgvcbc.Items.Clear();
foreach (object itemToAdd in o)
{
dgvcbc.Items.Add(itemToAdd);
}
}
dr.Close();
conn.Close();
}
}
setting the comboboxcell right after setting datasource doesnt work for me. it has to be done after binding operations completed. i choosed CellBeginEdit
example of empty dropdowns:
dgv1.datasource = datatable1;
dgv1.columns.add ( "cbxcol" , typeof(string) );
// different source for each comboboxcell in rows
var dict_rowInd_cbxDs = new Dictionary<int, object>();
dict_rowInd_cbxDs[1] = new list<string>(){"en" , "us"};
dict_rowInd_cbxDs[2] = new list<string>(){ "car", "bike"};
// !!!!!! setting comboboxcell after creating doesnt work here
foreach( row in dgv.Rows.asEnumerable() )
{
var cell = res_tn.dgv.CurrentCell as DataGridViewComboBoxCell;
cell.DataSource = dict_dgvRowI_cbxDs[res_tn.dgv.CurrentCell.RowIndex];
}
working example:
dgv1.datasource = datatable1;
dgv1.columns.add ( "cbxcol" , typeof(string) );
// different source for each comboboxcell in rows
var dict_rowInd_cbxDs = new Dictionary<int, object>();
dict_rowInd_cbxDs[1] = new list<string>(){"en" , "us"};
dict_rowInd_cbxDs[2] = new list<string>(){ "car", "bike"};
// cmboboxcell datasource Assingment Must be done after BindingComplete (not tested ) or cellbeginEdit (tested by me)
res_tn.dgv.CellBeginEdit += (s1, e1) => {
if (res_tn.dgv.CurrentCell is DataGridViewComboBoxCell) {
if (dict_dgvRowI_cbxDs.ContainsKey(res_tn.dgv.CurrentCell.RowIndex))
{
var cll = res_tn.dgv.CurrentCell as DataGridViewComboBoxCell;
cll.DataSource = dict_dgvRowI_cbxDs[res_tn.dgv.CurrentCell.RowIndex];
// required if it is list<mycustomClass>
// cll.DisplayMember = "ColName";
// cll.ValueMember = "This";
}
}
};
//Populate the Datatable with the Lookup lists
private DataTable typeDataTable(DataGridView dataGridView, Lookup<string, Element> type_Lookup, Dictionary<Element, string> type_dictionary, string strNewStyle, string strOldStyle, string strID, string strCount)
{
int row = 0;
DataTable dt = new DataTable();
dt.Columns.Add(strOldStyle, typeof(string));
dt.Columns.Add(strID, typeof(string));
dt.Columns.Add(strCount, typeof(int));
dt.Columns.Add("combobox", typeof(DataGridViewComboBoxCell));
//Add All Doc Types to ComboBoxes
DataGridViewComboBoxCell CmBx = new DataGridViewComboBoxCell();
CmBx.DataSource = new BindingSource(type_dictionary, null);
CmBx.DisplayMember = "Value";
CmBx.ValueMember = "Key";
//Add Style Comboboxes
DataGridViewComboBoxColumn Data_CmBx_Col = new DataGridViewComboBoxColumn();
Data_CmBx_Col.HeaderText = strNewStyle;
dataGridView.Columns.Add(addDataGrdViewComboBox(Data_CmBx_Col, type_dictionary));
setCellComboBoxItems(dataGridView, 1, 3, CmBx);
//Add style Rows
foreach (IGrouping<string, Element> StyleGroup in type_Lookup)
{
row++;
//Iterate through each group in the Igrouping
//Add Style Rows
dt.Rows.Add(StyleGroup.Key, row, StyleGroup.Count().ToString());
}
return dt;
}
private void setCellComboBoxItems(DataGridView dataGrid, int rowIndex, int colIndex, DataGridViewComboBoxCell CmBx)
{
DataGridViewComboBoxCell dgvcbc = (DataGridViewComboBoxCell)dataGrid.Rows[rowIndex].Cells[colIndex];
// You might pass a boolean to determine whether to clear or not.
dgvcbc.Items.Clear();
foreach (DataGridViewComboBoxCell itemToAdd in CmBx.Items)
{
dgvcbc.Items.Add(itemToAdd);
}