DataGridViewComboBoxColumn en ajoutant différents éléments à chaque ligne.
-
01-07-2019 - |
Question
Je construis une table à l'aide de DataGridView où un utilisateur peut sélectionner des éléments dans une liste déroulante dans chaque cellule. Pour simplifier le problème, disons que j'ai 1 colonne. J'utilise le DataGridViewComboBoxColumn dans le concepteur. J'essaie de faire en sorte que chaque ligne de cette colonne ait une liste différente d'éléments à choisir.
Est-ce possible?
La solution
Oui. Cela peut être fait en utilisant le DataGridViewComboBoxCell.
Voici un exemple de méthode pour ajouter les éléments à une seule cellule plutôt qu'à la colonne entière.
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);
}
}
Autres conseils
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == DataGridViewComboBoxColumnNumber)
{
setCellComboBoxItems(myDataGridView, e.RowIndex, e.ColumnIndex, someObj);
}
}
Au cas où quelqu'un trouverait ce fil, voici ma solution en VB 2008. Cela présente l'avantage de permettre d'affecter un identifiant à chaque valeur de la liste déroulante.
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
ceci est un exemple avec gridView qui a 2 comboboxColumns et lorsqu'un index sélectionné comboBoxColumns1 est modifié, chargez comboBoxColumns2 avec les données de deux colonnes différentes de la base de données.
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();
}
}
définir la comboboxcell juste après la définition de la source de données ne fonctionne pas pour moi . cela doit être fait une fois les opérations de liaison terminées. j'ai choisi CellBeginEdit
exemple de menus déroulants vides:
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];
}
exemple de travail:
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);
}