seleccionado saber marcar manejo evento event esta datagridviewcheckboxcolumn como c# winforms datagridview

saber - manejo de checkbox en datagridview c#



Cómo detectar el cambio de evento DataGridView CheckBox? (15)

Tengo una aplicación de winforms y quiero activar algún código cuando una casilla de verificación incrustada en un control DataGridView está marcada / desmarcada. Cada evento que he probado

  1. Desencadena tan pronto como se hace clic en CheckBox pero antes de que su estado verificado cambie, o
  2. Dispara solo cuando el CheckBox pierde su foco

Parece que no puedo encontrar un evento que se active inmediatamente después de que el estado verificado cambie.

Editar:

Lo que intento lograr es que cuando el estado comprobado de un CheckBox en un DataGridView cambie, los datos en otros dos DataGridView cambien. Sin embargo, todos los eventos que he usado, los datos en las otras grillas solo cambian después de que el CheckBox en el primer DataGridView pierde el foco.


Aquí hay un código:

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); } }


El Código hará un bucle en DataGridView y comprobará si la columna CheckBox está marcada

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; } } }


En el caso de CellContentClick puede usar esta estrategia:

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; } } }


Encontré que la solución de @ Killercam funciona, pero era un poco dudosa si el usuario hacía doble clic demasiado rápido. No estoy seguro de si otros encontraron que el caso tampoco. Encontré una solución más here .

Utiliza CellValueChanged y CellMouseUp la cuadrícula de CellMouseUp . Changhong explica eso

"La razón de esto es que el evento OnCellvalueChanged no se disparará hasta que DataGridView piense que usted ha completado la edición. Esto hace que los sentidos para una columna TextBox, como OnCellvalChanged no se dispare por cada golpe de tecla, pero no lo hace [ tiene sentido] para un CheckBox ".

Aquí está en acción por su ejemplo:

private void myDataGrid_OnCellValueChanged(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex == myCheckBoxColumn.Index && e.RowIndex != -1) { // Handle checkbox state change here } }

Y el código para indicar a la casilla de verificación que está haciendo la edición cuando se hace clic, en lugar de esperar hasta que el usuario abandone el campo:

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(); } }


Esto también maneja la activación del teclado.

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..... }


He encontrado una respuesta más simple a este problema. Simplemente uso la lógica inversa. El código está en VB pero no es muy diferente 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

Una de las mejores cosas sobre esto es que no hay necesidad de eventos múltiples.


He encontrado una respuesta más simple a este problema. Simplemente uso la lógica inversa. El código está en VB pero no es muy diferente de C #.

Private Sub DataGridView1_CellContentClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellContentClick 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

Una de las mejores cosas sobre esto es que no hay necesidad de eventos múltiples.


La eliminación del enfoque después de que el valor de la celda cambie permite que los valores se actualicen en DataGridView. Elimine el foco configurando CurrentCell en nulo.

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 solución de jsturtevants funcionó muy bien. Sin embargo, opté por hacer el procesamiento en el evento EndEdit. Prefiero este enfoque (en mi aplicación) porque, a diferencia del evento CellValueChanged, el evento EndEdit no se dispara mientras está poblando la cuadrícula.

Aquí está mi código (parte del cual es robado de 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(); } }


Lo que funcionó para mí fue CurrentCellDirtyStateChanged en combinación con datagridView1.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(); }


Para hacer esto cuando se usa devexpress xtragrid, es necesario manejar el evento EditValueChanged de un elemento de repositorio correspondiente como se describe here . También es importante llamar al método gridView1.PostEditor () para garantizar que el valor modificado se haya publicado. Aquí hay una implementación:

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); } } } }

Tenga en cuenta que debido a que xtragrid no proporciona un enumerador, es necesario usar un ciclo for para iterar sobre las filas.


Para manejar el evento CheckedChanged , primero debe hacer que CellContentClick (¡que no tiene el estado actual de CheckBox es!) Y luego llamar a CommitEdit . Esto activará el evento CellValueChanged que puede usar para hacer su trabajo. Esto es un descuido de Microsoft . Haga algo como lo siguiente ...

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(); }

Espero que esto ayude.

PS Verifique este artículo https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx


Puede forzar a la celda a confirmar el valor tan pronto como haga clic en la casilla de verificación y luego atrapar el evento CellValueChanged . CurrentCellDirtyStateChanged se activa tan pronto como hace clic en la casilla de verificación.

El siguiente código funciona para mí:

private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e) { SendKeys.Send("{tab}"); }

Luego puede insertar su código en el evento CellValueChanged .


Se trata de editar la celda, el problema es que la celda no se editó en realidad, por lo que debe guardar los cambios de la celda o la fila para obtener el evento cuando haga clic en la casilla de verificación para poder usar esta función:

datagridview.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange)

con esto puedes usarlo incluso con un evento diferente.


siguiendo Killercam''answer, Mi código

private void dgvProducts_CellContentClick(object sender, DataGridViewCellEventArgs e) { dgvProducts.CommitEdit(DataGridViewDataErrorContexts.Commit); }

y:

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 } } }