简体   繁体   English

在 DataGridView 中触发复选框值更改事件

[英]Triggering a checkbox value changed event in DataGridView

I have a grid view that has a check box column, and I want to trigger a drawing event as soon as the value of the cell is toggled.我有一个带有复选框列的网格视图,我想在单元格的值被切换后立即触发绘图事件。 I tried the ValueChaged and the CellEndEdit and BeginEdit, and chose the selection mode as CellSelect.我尝试了 ValueChaged 和 CellEndEdit 和 BeginEdit,并选择了 CellSelect 作为选择模式。 As for the the first 2 events, the event was triggered upon the finishing of the edit mode, like moving out of the current cell, or going back and forth.对于前2个事件,该事件是在编辑模式完成时触发的,例如移出当前单元格,或来回移动。 It's just a weird behavior.这只是一种奇怪的行为。

Is there anything that triggers the event on the grid view as soon as the cell value is changed?一旦单元格值发生变化,是否有任何东西会触发网格视图上的事件?

I use the CellContentClick event, which makes sure the user clicked the checkbox.我使用 CellContentClick 事件,它确保用户单击复选框。 It DOES fire multiple times even if the user stays in the same cell.即使用户停留在同一个单元格中,它也会多次触发。 The one issue is that the Value does not get updated, and always returns "false" for unchecked.一个问题是 Value 不会更新,并且总是返回“false”以表示未选中。 The trick is to use the .EditedFormattedValue property of the cell instead of the Value property.诀窍是使用单元格的 .EditedFormattedValue 属性而不是 Value 属性。 The EditedFormattedValue will track with the check mark and is what one wishes the Value had in it when the CellContentClick is fired. EditedFormattedValue 将使用复选标记进行跟踪,并且当 CellContentClick 被触发时,它是人们希望其中包含的值。

No need for a timer, no need for any fancy stuff, just use CellContentClick event and inspect the EditedFormattedValue to tell what state the checkbox is going into / just went into.不需要计时器,不需要任何花哨的东西,只需使用 CellContentClick 事件并检查 EditedFormattedValue 来判断复选框正在进入/刚刚进入的状态。 If EditedFormattedValue = true, the checkbox is getting checked.如果 EditedFormattedValue = true,则复选框被选中。

A colleague of mine recommends trapping the CurrentCellDirtyStateChanged event.我的一位同事建议捕获 CurrentCellDirtyStateChanged 事件。 See http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged.aspx .请参阅http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged.aspx

Another way is to handle the CellContentClick event (which doesn't give you the current value in the cell's Value property), call grid.CommitEdit(DataGridViewDataErrorContexts.Commit) to update the value which in turn will fire CellValueChanged where you can then get the actual (ie correct) DataGridViewCheckBoxColumn value.另一种方法是处理 CellContentClick 事件(它不会在单元格的 Value 属性中为您提供当前值),调用 grid.CommitEdit(DataGridViewDataErrorContexts.Commit) 来更新值,这反过来将触发 CellValueChanged,然后您可以获得实际(即正确)DataGridViewCheckBoxColumn 值。

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

private void grid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // do something with grid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value
}

Target .NET framework: 2.0目标 .NET 框架:2.0

Small update.... Make sure you use EditedFormattedValue instead of value as I tried value but it never give right status that is checked/unchecked most of the site still use value but as used in latest c# 2010 express below is one way to access..小更新......确保你使用EditedFormattedValue而不是value作为我尝试的value但它永远不会给出正确的状态, EditedFormattedValue选中/未选中的大多数站点仍然使用value但在下面最新的c# 2010 express中使用的是一种访问方式..

grdJobDetails.Rows[e.RowIndex].Cells[0].EditedFormattedValue

Also _CellValueChanged event suggested or used by few must be usable for some cases but if you are looking for every check/uncheck of cell make sure you use _CellContentClick else per my notice I see not every time _CellValueChanged is fired.. that is if the same checkbox is clicked over & over again it does not fire _CellValueChanged but if you click alternately for example you have two chekbox & click one after other _CellValueChanged event will be fired but usually if looking for event to fire everytime the any cell is check/uncheck _CellValueChanged is not fired.此外,少数人建议或使用的_CellValueChanged事件必须在某些情况下可用,但如果您正在查找单元格的每次检查/取消检查,请确保您使用_CellContentClick其他根据我的通知,我不是每次都看到_CellValueChanged被触发..如果相同复选框被反复点击它不会触发_CellValueChanged但如果你交替点击,例如你有两个_CellValueChanged并在其他_CellValueChanged事件将被触发之后点击一个,但通常如果在每次选中/取消选中任何单元格时寻找要触发的事件_CellValueChanged没有被解雇。

I had the same issue, but came up with a different solution:我有同样的问题,但想出了不同的解决方案:

If you make the column or the whole grid "Read Only" so that when the user clicks the checkbox it doesn't change value.如果您将列或整个网格设为“只读”,则当用户单击复选框时,它不会更改值。

Fortunately, the DataGridView.CellClick event is still fired.幸运的是, DataGridView.CellClick事件仍然被触发。 In my case I do the following in the cellClick event:就我而言,我在cellClick事件中执行以下cellClick

if (jM_jobTasksDataGridView.Columns[e.ColumnIndex].CellType.Name == "DataGridViewCheckBoxCell")

But you could check the column name if you have more than one checkbox column.但是,如果您有多个复选框列,则可以检查列名。

I then do all the modification / saving of the dataset myself.然后我自己完成数据集的所有修改/保存。

Try hooking into the CellContentClick event.尝试挂接到 CellContentClick 事件。 The DataGridViewCellEventArgs will have a ColumnIndex and a RowIndex so you can know if a ChecboxCell was in fact clicked. DataGridViewCellEventArgs 将有一个 ColumnIndex 和一个 RowIndex,因此您可以知道是否真的单击了 CheckboxCell。 The good thing about this event is that it will only fire if the actual checkbox itself was clicked.这个事件的好处是它只有在实际的复选框被点击时才会触发。 If you click on the white area of the cell around the checkbox, it won't fire.如果您单击复选框周围单元格的白色区域,它将不会触发。 This way, you're pretty much guaranteed that the checkbox value was changed when this event fires.这样,您几乎可以保证在此事件触发时复选框值已更改。 You can then call Invalidate() to trigger your drawing event, as well as a call to EndEdit() to trigger the end of the row's editing if you need that.然后,您可以调用 Invalidate() 来触发绘图事件,如果需要,还可以调用 EndEdit() 来触发行编辑的结束。

I finally implemented it this way我终于以这种方式实现了

  private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {

        if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
        {
            if (dataGridView1[e.ColumnIndex, e.RowIndex].GetContentBounds(e.RowIndex).Contains(e.Location))
            {
                cellEndEditTimer.Start();
            }
        }

    }

    private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
    { /*place your code here*/}


    private void cellEndEditTimer_Tick(object sender, EventArgs e)
    {
        dataGridView1.EndEdit();
        cellEndEditTimer.Stop();
    }

"EditingControlShowing" event doesn't fire on checkbox value change. “EditingControlShowing”事件不会在复选框值更改时触发。 Because display style of the checkbox cell doesn't not change.因为复选框单元格的显示样式不会改变。

The workaround i have used is as below.我使用的解决方法如下。 (I have used CellContentClick event) (我使用过 CellContentClick 事件)

    private void gGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        if (string.Compare(gGridView1.CurrentCell.OwningColumn.Name, "CheckBoxColumn") == 0)
        {
            bool checkBoxStatus = Convert.ToBoolean(gGridView1.CurrentCell.EditedFormattedValue);
            //checkBoxStatus gives you whether checkbox cell value of selected row for the
            //"CheckBoxColumn" column value is checked or not. 
            if(checkBoxStatus)
            {
                //write your code
            }
            else
            {
               //write your code
            }
        }
    }

The above has worked for me.以上对我有用。 Please let me know if need more help.如果需要更多帮助,请告诉我。

I found a simple solution.我找到了一个简单的解决方案。

Just change the cell focus after click on cell.单击单元格后只需更改单元格焦点。

private void DGV_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex == "Here checkbox column id or name") {
        DGV.Item(e.ColumnIndex, e.RowIndex + 1).Selected = true;
        //Here your code

    }
}

Don't forget to check if the column of your (ckeckbox + 1) index exist.不要忘记检查您的 (ckeckbox + 1) 索引的列是否存在。

Every one of the CellClick and CellMouseClick answers is wrong, because you can change the value of the cell with the keyboard and the event will not fire. CellClickCellMouseClick答案中的每一个都是错误的,因为您可以使用键盘更改单元格的值并且不会触发事件。 Additionally, CurrentCellDirtyStateChanged only fires once, which means if you check/uncheck the same box multiple times, you will only get one event.此外, CurrentCellDirtyStateChanged只触发一次,这意味着如果您多次选中/取消选中同一个框,您将只会收到一个事件。 Combining a few of the answers above gives the following simple solution:结合上面的几个答案给出了以下简单的解决方案:

private void dgvList_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dgvList.CurrentCell is DataGridViewCheckBoxCell)
        dgvList.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

private void dgvList_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
    // Now this will fire immediately when a check box cell is changed,
    // regardless of whether the user uses the mouse, keyboard, or touchscreen.
    //
    // Value property is up to date, you DO NOT need EditedFormattedValue here.
}

cellEndEditTimer.Start(); cellEndEditTimer.Start();

this line makes the datagridview update the list of checked boxes此行使 datagridview 更新复选框列表

Thank you.谢谢你。

Working with an unbound control (ie I manage the content programmatically), without the EndEdit() it only called the CurrentCellDirtyStateChanged once and then never again;使用未绑定的控件(即我以编程方式管理内容),如果没有 EndEdit(),它只调用 CurrentCellDirtyStateChanged 一次,然后再也不调用; but I found that with the EndEdit() CurrentCellDirtyStateChanged was called twice (the second probably caused by the EndEdit() but I didn't check), so I did the following, which worked best for me:但是我发现使用 EndEdit() CurrentCellDirtyStateChanged 被调用了两次(第二次可能是由 EndEdit() 引起的,但我没有检查),所以我做了以下操作,这对我来说效果最好:

    bool myGridView_DoCheck = false;
    private void myGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (!myGridView_DoCheck)
        {
            myGridView_DoCheck = true;
            myGridView.EndEdit();
            // do something here
        }
        else
            myGridView_DoCheck = false;
    }

Using the .EditedFormattedValue property solves the problem使用.EditedFormattedValue属性解决了这个问题

To be notified each time a checkbox in a cell toggles a value when clicked, you can use the CellContentClick event and access the preliminary cell value .EditedFormattedValue .要在每次单击单元格中的复选框切换值时收到通知,您可以使用CellContentClick事件并访问初始单元格值.EditedFormattedValue

As the event is fired the .EditedFormattedValue is not yet applied visually to the checkbox and not yet committed to the .Value property.当事件被触发时, .EditedFormattedValue尚未直观地应用于复选框,也尚未提交给 .Value 属性。

private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
   var checkbox = dataGridView1.CurrentCell as DataGridViewCheckBoxCell;

   bool isChecked = (bool)checkbox.EditedFormattedValue;

}

The event fires on each Click and the .EditedFormattedValue toggles事件在每次点击时触发, .EditedFormattedValue切换

I found a combination of the first two answers gave me what I needed.我发现前两个答案的组合给了我我需要的东西。 I used the CurrentCellDirtyStateChanged event and inspected the EditedFormattedValue.我使用了 CurrentCellDirtyStateChanged 事件并检查了 EditedFormattedValue。

private void dgv_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
   DataGridView dgv = (DataGridView)sender;
   DataGridViewCell cell = dgv.CurrentCell;
   if (cell.RowIndex >= 0 && cell.ColumnIndex == 3) // My checkbox column
     {
        // If checkbox checked, copy value from col 1 to col 2
        if (dgv.Rows[cell.RowIndex].Cells[cell.ColumnIndex].EditedFormattedValue != null && dgv.Rows[cell.RowIndex].Cells[cell.ColumnIndex].EditedFormattedValue.Equals(true))
        {
           dgv.Rows[cell.RowIndex].Cells[1].Value = dgv.Rows[cell.RowIndex].Cells[2].Value;
        }
     }
}

Use this code, when you want to use the checkedChanged event in DataGrid View:当您想在 DataGrid 视图中使用checkedChanged事件时,请使用以下代码:

private void grdBill_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
    grdBill.CurrentCell =  grdBill.Rows[grdBill.CurrentRow.Index].Cells["gBillNumber"];
}

private void grdBill_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    calcBill();
}

private void calcBill()
{
    listBox1.Items.Clear();
    for (int i = 0; i < grdBill.Rows.Count - 1; i++)
    {
        if (Convert.ToBoolean(grdBill.Rows[i].Cells["gCheck"].Value) == true)
        {
            listBox1.Items.Add(grdBill.Rows[i].Cells["gBillNumber"].Value.ToString());
        }
    }
}

Here, grdBill = DataGridView1, gCheck = CheckBox in GridView(First Column), gBillNumber = TextBox in Grid (Second column).这里, grdBill = DataGridView1, gCheck = CheckBox in GridView(First Column), gBillNumber = TextBox Grid 中的grdBill = DataGridView1, gCheck = CheckBox in GridView(First Column), gBillNumber = TextBox (第二列)。

So, when we want to fire checkchanged event for each click, first do the CellContentClick it will get fire when user clicked the Text box, then it will move the current cell to next column, so the CellEndEdit column will get fire, it will check the whether the checkbox is checked and add the "gBillNumber" in list box (in function calcBill).因此,当我们想为每次点击触发 checkchanged 事件时,首先执行 CellContentClick 当用户单击文本框时它会触发,然后它将当前单元格移动到下一列,因此 CellEndEdit 列会触发,它会检查是否选中复选框并在列表框中添加“gBillNumber”(在函数 calcBill 中)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM