DataGridViewcheckbox事件
我有一个winforms应用程序,并希望触发一些代码时embedded在DataGridView
控件中的checkbox被选中/取消选中。 每一个事件我都尝试过
- 触发一旦
CheckBox
被点击,但在它的检查状态改变之前,或 - 只有在
CheckBox
失去焦点时触发
我似乎无法find检查状态改变后立即触发的事件。
编辑:
我想实现的是,当一个DataGridView
CheckBox
的选中状态发生更改时,其他两个DataGridView
的数据会发生更改。 然而,我所使用的所有事件,其他网格中的数据仅在第一个DataGridView
的CheckBox
失去焦点后才发生变化。
要处理DatGridView
的CheckedChanged
事件,您必须首先获取CellContentClick
以触发(它没有CheckBox
当前状态!),然后调用CommitEdit
。 这将触发CellValueChanged
事件,您可以使用它来完成您的工作。 这是微软的疏忽 。 做一些如下的事情…
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(); }
我希望这有帮助。
PS检查这篇文章https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx
我发现@ Killercam的解决scheme工作,但如果用户双击太快,是有点狡猾。 不知道其他人是否也发现这种情况。 我在这里find另一个解决scheme。
它使用数据网格的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 } }
而代码告诉checkbox它被点击时完成编辑,而不是等到用户离开字段:
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的解决scheme效果很好。 但是,我select在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 } } }
这是关于编辑单元格的问题,单元格的问题实际上并没有被编辑,所以当你点击checkbox时你需要保存单元格或者行的变化来获取事件,这样你可以使用这个函数:
datagridview.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange)
有了这个,你可以使用它甚至不同的事件。
我find了一个更简单的答案来解决这个问题。 我只是使用反向逻辑。 代码在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列是否被选中
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; } } }
为了在使用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循环遍历行。
我find了一个更简单的答案来解决这个问题。 我只是使用反向逻辑。 代码在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); } }
单击checkbox后,您可以强制单元格提交值,然后捕获CellValueChanged事件。 单击checkbox后, CurrentCellDirtyStateChanged将立即触发。
以下代码适用于我:
private void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e) { SendKeys.Send("{tab}"); }
然后,您可以将您的代码插入到CellValueChanged事件中。