如何检测DataGridView CheckBox事件的变化?

PJW*_*PJW 77 c# datagridview winforms

我有一个winforms应用程序,并希望在DataGridView选中/取消选中控件中嵌入的复选框时触发一些代码.我尝试过的每一件事

  1. CheckBox单击时但在其检查状态发生变化之前触发,或者
  2. 只有在CheckBox失去焦点时触发

我似乎无法找到在检查状态更改后立即触发的事件.


编辑:

我想实现的是,当检查的状态CheckBox的一个DataGridView变化,在其他两个数据DataGridView变迁.然而,我使用的所有事件中,其他网格中的数据仅CheckBox在第一次DataGridView失去焦点后才会发生变化.

Moo*_*ght 85

要处理DatGridViews CheckedChanged事件,你必须先CellContentClick触发(没有CheckBoxes当前状态!)然后调用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();
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.

PS查看这篇文章https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx

  • 这是一个很好的解决方案,但如果用户点击几次则不起作用,另一个已发布在http://stackoverflow.com/questions/11843488/datagridview-checkbox-event#15011844 (3认同)
  • 如果您也将相同的代码从“CellContentClick”添加到“CellContentDoubleClick”中,则效果非常好。即使选择了单元格但未单击复选框,“CellMouseUp”也会触发 - 这不是所需的行为。 (2认同)

jst*_*ant 81

我找到了@ Killercam的解决方案,但是如果用户双击太快就会有点狡猾.不确定是否其他人发现了这种情况.我找到了另一种解决方案在这里.

它使用datagrid CellValueChangedCellMouseUp.长虹解释说

"原因是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
    }
}
Run Code Online (Sandbox Code Playgroud)

并且告诉复选框的代码在单击时完成编辑,而不是等到用户离开字段:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我遇到了响应者注意到的双击问题,这个问题比正确处理这个问题的第一个解决方案要好得多. (3认同)
  • 如果您使用空格键切换切换怎么办? (3认同)
  • 为了“修复”空格键问题,我在表单上将“KeyPreview”设置为 true,并在“e.KeyCode == Keys.Space”时设置“e.Handled = true”。换句话说,我只是禁用了键盘编辑。 (2认同)

Mar*_*rth 9

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,但最好使用CellContentClick而不是CellMouseUp,因为当用户单击单元格内的任何位置时,将调用CellMouseUp,而仅在选中复选框时才调用前者。 (2认同)

小智 8

Ben Voigt 在上面的评论回复中找到了最佳解决方案:

private void dgvStandingOrder_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dgvStandingOrder.CurrentCell is DataGridViewCheckBoxCell)
        dgvStandingOrder.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
Run Code Online (Sandbox Code Playgroud)

说真的,这就是你所需要的。


小智 6

这是一些代码:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此答案包含正确答案,可处理鼠标和键盘交互以及不离开单元格的重复交互。但只需要最后一个处理程序——从 `CurrentCellDirtyStateChanged` 调用 `CommitEdit` 是整个解决方案。 (3认同)

小智 6

按照 Killercam'answer,我的代码

private void dgvProducts_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        dgvProducts.CommitEdit(DataGridViewDataErrorContexts.Commit);
    }
Run Code Online (Sandbox Code Playgroud)

和 :

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
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)


小智 5

这也处理键盘激活.

    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.....
    }
Run Code Online (Sandbox Code Playgroud)