繁体   English   中英

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

[英]Triggering a checkbox value changed event in DataGridView

我有一个带有复选框列的网格视图,我想在单元格的值被切换后立即触发绘图事件。 我尝试了 ValueChaged 和 CellEndEdit 和 BeginEdit,并选择了 CellSelect 作为选择模式。 对于前2个事件,该事件是在编辑模式完成时触发的,例如移出当前单元格,或来回移动。 这只是一种奇怪的行为。

一旦单元格值发生变化,是否有任何东西会触发网格视图上的事件?

我使用 CellContentClick 事件,它确保用户单击复选框。 即使用户停留在同一个单元格中,它也会多次触发。 一个问题是 Value 不会更新,并且总是返回“false”以表示未选中。 诀窍是使用单元格的 .EditedFormattedValue 属性而不是 Value 属性。 EditedFormattedValue 将使用复选标记进行跟踪,并且当 CellContentClick 被触发时,它是人们希望其中包含的值。

不需要计时器,不需要任何花哨的东西,只需使用 CellContentClick 事件并检查 EditedFormattedValue 来判断复选框正在进入/刚刚进入的状态。 如果 EditedFormattedValue = true,则复选框被选中。

我的一位同事建议捕获 CurrentCellDirtyStateChanged 事件。 请参阅http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.currentcelldirtystatechanged.aspx

另一种方法是处理 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
}

目标 .NET 框架:2.0

小更新......确保你使用EditedFormattedValue而不是value作为我尝试的value但它永远不会给出正确的状态, EditedFormattedValue选中/未选中的大多数站点仍然使用value但在下面最新的c# 2010 express中使用的是一种访问方式..

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

此外,少数人建议或使用的_CellValueChanged事件必须在某些情况下可用,但如果您正在查找单元格的每次检查/取消检查,请确保您使用_CellContentClick其他根据我的通知,我不是每次都看到_CellValueChanged被触发..如果相同复选框被反复点击它不会触发_CellValueChanged但如果你交替点击,例如你有两个_CellValueChanged并在其他_CellValueChanged事件将被触发之后点击一个,但通常如果在每次选中/取消选中任何单元格时寻找要触发的事件_CellValueChanged没有被解雇。

我有同样的问题,但想出了不同的解决方案:

如果您将列或整个网格设为“只读”,则当用户单击复选框时,它不会更改值。

幸运的是, DataGridView.CellClick事件仍然被触发。 就我而言,我在cellClick事件中执行以下cellClick

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

但是,如果您有多个复选框列,则可以检查列名。

然后我自己完成数据集的所有修改/保存。

尝试挂接到 CellContentClick 事件。 DataGridViewCellEventArgs 将有一个 ColumnIndex 和一个 RowIndex,因此您可以知道是否真的单击了 CheckboxCell。 这个事件的好处是它只有在实际的复选框被点击时才会触发。 如果您单击复选框周围单元格的白色区域,它将不会触发。 这样,您几乎可以保证在此事件触发时复选框值已更改。 然后,您可以调用 Invalidate() 来触发绘图事件,如果需要,还可以调用 EndEdit() 来触发行编辑的结束。

我终于以这种方式实现了

  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”事件不会在复选框值更改时触发。 因为复选框单元格的显示样式不会改变。

我使用的解决方法如下。 (我使用过 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
            }
        }
    }

以上对我有用。 如果需要更多帮助,请告诉我。

我找到了一个简单的解决方案。

单击单元格后只需更改单元格焦点。

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

    }
}

不要忘记检查您的 (ckeckbox + 1) 索引的列是否存在。

CellClickCellMouseClick答案中的每一个都是错误的,因为您可以使用键盘更改单元格的值并且不会触发事件。 此外, CurrentCellDirtyStateChanged只触发一次,这意味着如果您多次选中/取消选中同一个框,您将只会收到一个事件。 结合上面的几个答案给出了以下简单的解决方案:

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

此行使 datagridview 更新复选框列表

谢谢你。

使用未绑定的控件(即我以编程方式管理内容),如果没有 EndEdit(),它只调用 CurrentCellDirtyStateChanged 一次,然后再也不调用; 但是我发现使用 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;
    }

使用.EditedFormattedValue属性解决了这个问题

要在每次单击单元格中的复选框切换值时收到通知,您可以使用CellContentClick事件并访问初始单元格值.EditedFormattedValue

当事件被触发时, .EditedFormattedValue尚未直观地应用于复选框,也尚未提交给 .Value 属性。

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

   bool isChecked = (bool)checkbox.EditedFormattedValue;

}

事件在每次点击时触发, .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;
        }
     }
}

当您想在 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());
        }
    }
}

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

因此,当我们想为每次点击触发 checkchanged 事件时,首先执行 CellContentClick 当用户单击文本框时它会触发,然后它将当前单元格移动到下一列,因此 CellEndEdit 列会触发,它会检查是否选中复选框并在列表框中添加“gBillNumber”(在函数 calcBill 中)。

暂无
暂无

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

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