C# 如何检测 DataGridView CheckBox 事件变化?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11843488/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 19:28:45  来源:igfitidea点击:

How to detect DataGridView CheckBox event change?

c#winformsdatagridview

提问by PJW

I have a winforms app and want to trigger some code when a checkbox embedded in a DataGridViewcontrol is checked / unchecked. Every event I have tried either

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

  1. Triggers as soon as the CheckBoxis clicked but before its checked state changes, or
  2. Triggers only once the CheckBoxlooses its focus
  1. CheckBox单击 后但在其选中状态更改之前立即触发,或
  2. 仅在CheckBox失去焦点时触发

I can't seem to find event that triggers immediately after the checked state changes.

我似乎无法找到在选中状态更改后立即触发的事件。



Edit:

编辑:

What I am trying to achieve is that when the checked state of a CheckBoxin one DataGridViewchanges, the data in two other DataGridViews changes. Yet all the events I have used, the data in the other grids only changes after the CheckBoxin the first DataGridViewlooses focus.

我想要实现的是,当 a CheckBoxin one的选中状态DataGridView发生变化时,另外两个DataGridViews 中的数据也会发生变化。然而,我使用过的所有事件,其他网格中的数据只会CheckBox在第一个DataGridView失去焦点后发生变化。

采纳答案by MoonKnight

To handle the DatGridViews CheckedChangedevent you must first get the CellContentClickto fire (which does not have the CheckBoxes current state!) then call CommitEdit. This will in turn fire the CellValueChangedevent which you can use to do your work. This is an oversight by Microsoft. Do some thing like the following...

要处理DatGridViewsCheckedChanged事件,您必须首先CellContentClick触发s事件(它没有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();
}

I hope this helps.

我希望这有帮助。

P.S. Check this article https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged(v=vs.110).aspx

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

回答by Nay Lin Aung

Here is some 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);
    }
}

回答by jsturtevant

I found @Killercam's solution to work but was a bit dodgy if the user double clicked too fast. Not sure if other's found that the case either. I found a another solution here.

我发现@Killercam 的解决方案可以工作,但如果用户双击太快就有点狡猾了。不知道其他人是否也发现了这种情况。我在这里找到了另一个解决方案。

It uses the datagrid's CellValueChangedand CellMouseUp. Changhong explains that

它使用数据网格的CellValueChangedCellMouseUp. 长虹解释说

"The reason for that is OnCellvalueChanged event won't fire until the DataGridView thinks you have completed editing. This makes senses for a TextBox Column, as OnCellvalueChanged wouldn't [bother] to fire for each key strike, but it doesn't [make sense] for a CheckBox."

“这样做的原因是 OnCellvalueChanged 事件在 DataGridView 认为您已经完成编辑之前不会触发。这对于 TextBox 列来说是有意义的,因为 OnCellvalueChanged 不会[打扰] 为每个按键触发,但它不会 [对 CheckBox 有意义]。”

Here it is in action from his example:

这是他的例子中的行动:

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

And the code to tell the checkbox it is done editing when it is clicked, instead of waiting till the user leaves the field:

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

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

回答by beetroot123

What worked for me was CurrentCellDirtyStateChangedin combination with datagridView1.EndEdit()

对我有用的是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();
}

回答by Ngh?a Lê

following Killercam'answer, My code

按照 Killercam'answer,我的代码

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

and :

和 :

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

回答by Chuck Fecteau

This also handles the keyboard activation.

这也处理键盘激活。

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

回答by Mark Ainsworth

jsturtevants's solution worked great. However, I opted to do the processing in the EndEdit event. I prefer this approach (in my application) because, unlike the CellValueChanged event, the EndEdit event does not fire while you are populating the grid.

jsturtevants 的解决方案效果很好。但是,我选择在 EndEdit 事件中进行处理。我更喜欢这种方法(在我的应用程序中),因为与 CellValueChanged 事件不同,EndEdit 事件在您填充网格时不会触发。

Here is my code (part of which is stolen from jsturtevant:

这是我的代码(其中一部分是从 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();
    }
}

回答by ahmedcool166

It's all about editing the cell, the problem that is the cell didn't edited actually, so you need to save The changes of the cell or the row to get the event when you click the check box so you can use this function:

都是关于编辑单元格的,问题是单元格实际上没有被编辑,所以你需要保存单元格或行的变化来获取当你点击复选框时的事件,这样你就可以使用这个功能:

datagridview.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange)

with this you can use it even with a different event.

有了这个,您甚至可以在不同的事件中使用它。

回答by E Coder

The Code will loop in DataGridView and Will check if CheckBox Column is Checked

代码将在 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;
        }
    }
}

回答by majjam

To do this when using the devexpress xtragrid, it is necessary to handle the EditValueChangedevent of a corresponding repository item as described here. It is also important to call the gridView1.PostEditor() method to ensure the changed value has been posted. Here is an implementation:

要在使用 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);
                    }
                }
            }
        }

Note that because the xtragrid doesnt provide an enumerator it is necessary to use a for loop to iterate over rows.

请注意,因为 xtragrid 不提供枚举器,所以有必要使用 for 循环来遍历行。