Как определить событие EventGridView CheckBox?

У меня есть приложение winforms и вы хотите запустить какой-то код, когда флажок, встроенный в DataGridView управления DataGridView проверяется / не проверяется. Каждое событие, которое я пробовал

  1. Триггеры, как только CheckBox но до того, как будет изменено его состояние, или
  2. Триггеры только после того, как CheckBox теряет фокус

Я не могу найти событие, которое срабатывает сразу после изменения состояния проверки.


Редактировать:

Я пытаюсь добиться того, что когда проверенное состояние CheckBox в одном DataGridView изменяется, данные в двух других DataGridView с меняются. Однако все события, которые я использовал, данные в других gridх меняются только после того, как CheckBox в первом DataGridView теряет фокус.

Чтобы обработать DatGridView CheckedChanged вы должны сначала запустить CellContentClick (который не имеет текущего состояния CheckBox !), А затем вызвать CommitEdit . Это, в свою очередь, CellValueChanged событие CellValueChanged которое вы можете использовать для выполнения своей работы. Это надзор со стороны Microsoft . Сделайте что-нибудь вроде следующего …

 private void dataGridViewSites_CellContentClick(object sender, DataGridViewCellEventArgs e) { dataGridViewSites.CommitEdit(DataGridViewDataErrorContexts.Commit); } ///  /// Works with the above. ///  private void dataGridViewSites_CellValueChanged(object sender, DataGridViewCellEventArgs e) { UpdateDataGridViewSite(); } 

Надеюсь, это поможет.

PS Проверьте эту статью https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx

Я нашел решение @ Killercam для работы, но было немного изворотливым, если пользователь дважды щелкнул слишком быстро. Не уверен, что другие нашли это дело. Я нашел здесь другое решение.

Он использует CellValueChanged и CellMouseUp . Чанхун объясняет, что

«Причина этого – событие OnCellvalueChanged не срабатывает до тех пор, пока DataGridView не подумает, что вы закончили редактирование. Это создает смысл для столбца TextBox, поскольку OnCellvalueChanged не будет [беспокоить], чтобы стрелять для каждого нажатия клавиши, но это не [ иметь смысл] для CheckBox. ”

Здесь он находится в действии из своего примера:

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

И код, чтобы сообщить флажку, он будет редактироваться, когда он щелкнут, вместо того, чтобы ждать, пока пользователь покинет поле:

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

Решение jsturtevants отлично поработало. Однако я решил сделать обработку в событии EndEdit. Я предпочитаю этот подход (в моем приложении), потому что, в отличие от события CellValueChanged, событие EndEdit не срабатывает, когда вы заполняете сетку.

Вот мой код (часть которого украдена у 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(); } } 

Это также позволяет активировать клавиатуру.

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

следующий Killercam’answer, Мой код

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

а также :

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

Речь идет о редактировании ячейки, проблема в том, что ячейка не редактировалась на самом деле, поэтому вам нужно сохранить изменения ячейки или строки, чтобы получить событие, когда вы нажмете этот флажок, чтобы вы могли использовать эту функцию:

 datagridview.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange) 

с этим вы можете использовать его даже с другим событием.

Я нашел более простой ответ на эту проблему. Я просто использую обратную логику. Код находится в VB, но он не сильно отличается от 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 

Одна из лучших вещей в этом – это не необходимость в нескольких событиях.

Вот какой код:

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

Для меня работала CurrentCellDirtyStateChanged в сочетании с 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(); } 

Код будет зацикливаться на DataGridView и проверяет, проверена ли CheckBox Column

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

В случае CellContentClick вы можете использовать эту страtagsю:

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

Чтобы сделать это при использовании devexpress xtragrid, необходимо обработать событие EditValueChanged соответствующего элемента репозитория, как описано здесь . Также важно вызвать метод gridView1.PostEditor (), чтобы гарантировать, что измененное значение было опубликовано. Вот реализация:

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

Обратите внимание, что поскольку xtragrid не предоставляет перечислитель, необходимо использовать цикл for для итерации по строкам.

Я нашел более простой ответ на эту проблему. Я просто использую обратную логику. Код находится в VB, но он не сильно отличается от 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 

Одна из лучших вещей в этом – это не необходимость в нескольких событиях.

Удаление фокуса после изменения значения ячейки позволяет обновлять значения в DataGridView. Удалите фокус, установив CurrentCell в значение 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); } } 

Вы можете заставить ячейку зафиксировать значение, как только вы установите флажок, а затем поймаете событие CellValueChanged . CurrentCellDirtyStateChanged срабатывает, как только вы нажимаете этот флажок.

Для меня работает следующий код:

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

Затем вы можете вставить свой код в событие CellValueChanged .

  • C # Winform ProgressBar и BackgroundWorker
  • Управление объемным микшером
  • Настройка OpenFileDialog
  • Каков «правильный» способ принести приложение Windows Forms на передний план?
  • InvalidOperationException - объект в настоящее время используется в другом месте
  • Событие, когда окно максимизируется / не максимизируется
  • C # - Как сделать две формы ссылки друг на друга
  • Почему загрузка формы не может устранить исключение?
  • Как я могу исправить приложение Windows .NET при запуске с кодом исключения: 0xE0434352?
  • Правильная локализация приложения WinForms
  • Как отключить создание пустого файла журнала при запуске приложения?
  • Давайте будем гением компьютера.