J'ai une application winforms et je souhaite déclencher du code lorsqu'une case à cocher intégrée dans un DataGridView
contrôle est cochée / décochée. Chaque événement que j'ai essayé soit
- Se déclenche dès que l'utilisateur
CheckBox
clique sur mais avant que son état vérifié ne change, ou - Ne se déclenche qu'une fois que le
CheckBox
focus perd sa concentration
Je n'arrive pas à trouver un événement qui se déclenche immédiatement après le changement d'état vérifié.
Éditer:
Ce que j'essaie de réaliser, c'est que lorsque l'état vérifié d'un CheckBox
dans un DataGridView
change, les données de deux autres DataGridView
changent. Pourtant, tous les événements que j'ai utilisés, les données des autres grilles ne changent qu'après que CheckBox
le premier DataGridView
perd son focus.
CurrentCellDirtyStateChanged
événement?Réponses:
Pour gérer l' événement
DatGridView
sCheckedChanged
, vous devez d'abord obtenir leCellContentClick
to fire (qui n'a pas l'CheckBox
état actuel de es!) Puis appelerCommitEdit
. Cela déclenchera à son tour l'CellValueChanged
événement que vous pourrez utiliser pour faire votre travail. Il s'agit d'un oubli de Microsoft . Faites quelque chose comme ce qui suit ...private void dataGridViewSites_CellContentClick(object sender, DataGridViewCellEventArgs e) { dataGridViewSites.CommitEdit(DataGridViewDataErrorContexts.Commit); } /// <summary> /// Works with the above. /// </summary> private void dataGridViewSites_CellValueChanged(object sender, DataGridViewCellEventArgs e) { UpdateDataGridViewSite(); }
J'espère que ça aide.
PS Consultez cet article https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx
la source
DataGridViewCheckBox
. Ce n'est pas WPF et double-cliquer sur le contrôle ne rompt aucune liaison de données, c'est WinForms. Un double-clic peut ne pas mettre à jour le contrôle visuellement, mais il ne casse rien et dans ce cas, la solution ci-dessous est peut-être la meilleure. Merci.CellContentClick
dansCellContentDoubleClick
.CellMouseUp
Cela se déclenchera même si la cellule est sélectionnée mais que la case n'est pas cochée - ce qui n'est pas le comportement souhaité.J'ai trouvé que la solution de @ Killercam fonctionnait, mais j'étais un peu douteuse si l'utilisateur double-cliquait trop rapidement. Je ne sais pas si d'autres ont trouvé le cas non plus. J'ai trouvé une autre solution ici .
Il utilise les datagrid
CellValueChanged
etCellMouseUp
. Changhong explique queLe voici en action d'après son exemple:
private void myDataGrid_OnCellValueChanged(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1) { // Handle checkbox state change here } }
Et le code pour indiquer à la case à cocher qu'il est terminé de modifier quand il est cliqué, au lieu d'attendre que l'utilisateur quitte le champ:
private void myDataGrid_OnCellMouseUp(object sender,DataGridViewCellMouseEventArgs e) { // End of edition on each click on column of checkbox if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1) { myDataGrid.EndEdit(); } }
Modifier: un événement DoubleClick est traité séparément d'un événement MouseUp. Si un événement DoubleClick est détecté, l'application ignorera entièrement le premier événement MouseUp. Cette logique doit être ajoutée à l'événement CellDoubleClick en plus de l'événement MouseUp:
private void myDataGrid_OnCellDoubleClick(object sender,DataGridViewCellEventArgs e) { // End of edition on each click on column of checkbox if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1) { myDataGrid.EndEdit(); } }
la source
KeyPreview
sur true sur le formulaire et quande.KeyCode == Keys.Space
, définie.Handled = true
. En d'autres termes, je viens de désactiver l'édition du clavier.La solution de jsturtevants a très bien fonctionné. Cependant, j'ai choisi de faire le traitement dans l'événement EndEdit. Je préfère cette approche (dans mon application) car, contrairement à l'événement CellValueChanged, l'événement EndEdit ne se déclenche pas lorsque vous remplissez la grille.
Voici mon code (dont une partie est volée à jsturtevant:
private void gridCategories_CellEndEdit(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == gridCategories.Columns["AddCategory"].Index) { //do some stuff } } private void gridCategories_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e) { if (e.ColumnIndex == gridCategories.Columns["AddCategory"].Index) { gridCategories.EndEdit(); } }
la source
CellContentClick
au lieu deCellMouseUp
car ce dernier sera appelé lorsque l'utilisateur cliquera n'importe où dans la cellule alors que le premier n'est appelé que lorsque la case est cochée.Cela gère également l'activation du clavier.
private void dgvApps_CellContentClick(object sender, DataGridViewCellEventArgs e) { if(dgvApps.CurrentCell.GetType() == typeof(DataGridViewCheckBoxCell)) { if (dgvApps.CurrentCell.IsInEditMode) { if (dgvApps.IsCurrentCellDirty) { dgvApps.EndEdit(); } } } } private void dgvApps_CellValueChanged(object sender, DataGridViewCellEventArgs e) { // handle value changed..... }
la source
Voici un code:
private void dgvStandingOrder_CellContentClick(object sender, DataGridViewCellEventArgs e) { if (dgvStandingOrder.Columns[e.ColumnIndex].Name == "IsSelected" && dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell) { bool isChecked = (bool)dgvStandingOrder[e.ColumnIndex, e.RowIndex].EditedFormattedValue; if (isChecked == false) { dgvStandingOrder.Rows[e.RowIndex].Cells["Status"].Value = ""; } dgvStandingOrder.EndEdit(); } } private void dgvStandingOrder_CellEndEdit(object sender, DataGridViewCellEventArgs e) { dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit); } private void dgvStandingOrder_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell) { dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit); } }
la source
CommitEdit
depuisCurrentCellDirtyStateChanged
est la solution complète.suite à Killercam'answer, Mon code
private void dgvProducts_CellContentClick(object sender, DataGridViewCellEventArgs e) { dgvProducts.CommitEdit(DataGridViewDataErrorContexts.Commit); }
et :
private void dgvProducts_CellValueChanged(object sender, DataGridViewCellEventArgs e) { if (dgvProducts.DataSource != null) { if (dgvProducts.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString() == "True") { //do something } else { //do something } } }
la source
Il s'agit de modifier la cellule, le problème est que la cellule n'a pas été modifiée en fait, vous devez donc enregistrer les modifications de la cellule ou de la ligne pour obtenir l'événement lorsque vous cliquez sur la case à cocher afin que vous puissiez utiliser cette fonction:
avec cela, vous pouvez l'utiliser même avec un événement différent.
la source
J'ai trouvé une réponse plus simple à ce problème. J'utilise simplement la logique inverse. Le code est en VB mais ce n'est pas très différent de C #.
Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick Dim _ColumnIndex As Integer = e.ColumnIndex Dim _RowIndex As Integer = e.RowIndex 'Uses reverse logic for current cell because checkbox checked occures 'after click 'If you know current state is False then logic dictates that a click 'event will set it true 'With these 2 check boxes only one can be true while both can be off If DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False And DataGridView1.Rows(_RowIndex).Cells("Column3").Value = True Then DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False End If If DataGridView1.Rows(_RowIndex).Cells("Column3").Value = False And DataGridView1.Rows(_RowIndex).Cells("Column2").Value = True Then DataGridView1.Rows(_RowIndex).Cells("Column2").Value = False End If End Sub
L'une des meilleures choses à ce sujet est de ne pas avoir besoin de plusieurs événements.
la source
Ce qui a fonctionné pour moi était
CurrentCellDirtyStateChanged
en combinaison avecdatagridView1.EndEdit()
private void dataGridView1_CurrentCellDirtyStateChanged( object sender, EventArgs e ) { if ( dataGridView1.CurrentCell is DataGridViewCheckBoxCell ) { DataGridViewCheckBoxCell cb = (DataGridViewCheckBoxCell)dataGridView1.CurrentCell; if ( (byte)cb.Value == 1 ) { dataGridView1.CurrentRow.Cells["time_loadedCol"].Value = DateTime.Now.ToString(); } } dataGridView1.EndEdit(); }
la source
Le code boucle dans DataGridView et vérifie si la colonne CheckBox est vérifiée
private void dgv1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e) { if (e.ColumnIndex == 0 && e.RowIndex > -1) { dgv1.CommitEdit(DataGridViewDataErrorContexts.Commit); var i = 0; foreach (DataGridViewRow row in dgv1.Rows) { if (Convert.ToBoolean(row.Cells[0].Value)) { i++; } } //Enable Button1 if Checkbox is Checked if (i > 0) { Button1.Enabled = true; } else { Button1.Enabled = false; } } }
la source
Dans le cas où CellContentClick, vous pouvez utiliser cette stratégie:
private void myDataGrid_CellContentClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == 2)//set your checkbox column index instead of 2 { //When you check if (Convert.ToBoolean(myDataGrid.Rows[e.RowIndex].Cells[2].EditedFormattedValue) == true) { //EXAMPLE OF OTHER CODE myDataGrid.Rows[e.RowIndex].Cells[5].Value = DateTime.Now.ToShortDateString(); //SET BY CODE THE CHECK BOX myDataGrid.Rows[e.RowIndex].Cells[2].Value = 1; } else //When you decheck { myDataGrid.Rows[e.RowIndex].Cells[5].Value = String.Empty; //SET BY CODE THE CHECK BOX myDataGrid.Rows[e.RowIndex].Cells[2].Value = 0; } } }
la source
J'ai essayé quelques réponses à partir d'ici, mais j'ai toujours eu une sorte de problème (comme un double-clic ou l'utilisation du clavier). Donc, j'ai combiné certains d'entre eux et j'ai obtenu un comportement cohérent (ce n'est pas parfait, mais fonctionne correctement).
void gridView_CellContentClick(object sender, DataGridViewCellEventArgs e) { if(gridView.CurrentCell.GetType() != typeof(DataGridViewCheckBoxCell)) return; if(!gridView.CurrentCell.IsInEditMode) return; if(!gridView.IsCurrentCellDirty) return; gridView.EndEdit(); } void gridView_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e) { if(e.ColumnIndex == gridView.Columns["cFlag"].Index && e.RowIndex >= 0) gridView.EndEdit(); } void gridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) { if(e.ColumnIndex != gridView.Columns["cFlag"].Index || e.RowIndex < 0) return; // Do your stuff here. }
la source
Pour ce faire lors de l'utilisation de devexpress xtragrid, il est nécessaire de gérer l' événement EditValueChanged d'un élément de référentiel correspondant comme décrit ici . Il est également important d'appeler la méthode gridView1.PostEditor () pour s'assurer que la valeur modifiée a été publiée. Voici une implémentation:
private void RepositoryItemCheckEdit1_EditValueChanged(object sender, System.EventArgs e) { gridView3.PostEditor(); var isNoneOfTheAboveChecked = false; for (int i = 0; i < gridView3.DataRowCount; i++) { if ((bool) (gridView3.GetRowCellValue(i, "NoneOfTheAbove")) && (bool) (gridView3.GetRowCellValue(i, "Answer"))) { isNoneOfTheAboveChecked = true; break; } } if (isNoneOfTheAboveChecked) { for (int i = 0; i < gridView3.DataRowCount; i++) { if (!((bool)(gridView3.GetRowCellValue(i, "NoneOfTheAbove")))) { gridView3.SetRowCellValue(i, "Answer", false); } } } }
Notez que puisque le xtragrid ne fournit pas d'énumérateur, il est nécessaire d'utiliser une boucle for pour parcourir les lignes.
la source
La suppression du focus après les modifications de valeur de cellule permet aux valeurs de se mettre à jour dans DataGridView. Supprimez le focus en définissant CurrentCell sur null.
private void DataGridView1OnCellValueChanged(object sender, DataGridViewCellEventArgs dataGridViewCellEventArgs) { // Remove focus dataGridView1.CurrentCell = null; // Put in updates Update(); } private void DataGridView1OnCurrentCellDirtyStateChanged(object sender, EventArgs eventArgs) { if (dataGridView1.IsCurrentCellDirty) { dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); } }
la source
Vous pouvez forcer la cellule à valider la valeur dès que vous cliquez sur la case à cocher, puis interceptez l' événement CellValueChanged . Le CurrentCellDirtyStateChanged feu dès que vous cliquez sur la case à cocher.
Le code suivant fonctionne pour moi:
private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e) { SendKeys.Send("{tab}"); }
Vous pouvez ensuite insérer votre code dans l' événement CellValueChanged .
la source
Ben Voigt a trouvé la meilleure solution dans un commentaire-réponse ci-dessus:
private void dgvStandingOrder_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell) dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit); }
Sérieusement, c'est TOUT ce dont vous avez besoin.
la source