数据网格视图 - 如何使复选框充当单选按钮

本文关键字:复选框 单选按钮 何使 数据网 网格 视图 数据 | 更新日期: 2023-09-27 18:33:17

我有一个Windows窗体应用程序,它在DataGridView中显示对象列表。

此控件将布尔值呈现为复选框。

对象属性中有一组三个互斥的复选框。其中最多一个可能是真的。因此,我希望复选框像一组单选按钮一样。

只是老家伙的一句旁白:我想现在的人甚至不知道为什么这些被称为单选按钮。在过去,汽车中的收音机有 4 或 5 个按钮,按下其中任何一个按钮都会导致所有其他按钮弹出。它们是相互排斥的。如今,"单选按钮"可能不是一个有用的描述,因为收音机不再有这样的按钮,我不认为了。

我该怎么做? 我想如果我将"CheckedChanged"事件附加到复选框,并且我知道该行,我将能够找到所有其他复选框。

我可以

挂接什么事件来在首次呈现复选框控件时获取该控件,以便我可以将 CheckedChanged 事件附加到它? 我知道DataGridView.CellFormatting,但我认为这是错误的,因为每次 DataGridView 绘制时都会调用它。 我真的需要一个仅在第一次渲染 DGV 时调用的事件。

数据网格视图 - 如何使复选框充当单选按钮

感谢 KeithS 的有用答案。

当我在文档中查找CellValueChanged时,我发现这很有帮助:

DataGridView.CellValueChanged 事件在提交用户指定的值时发生,这通常在焦点离开单元格时发生。

但是,对于复选框单元格,您通常需要立即处理更改。若要在单击单元格时提交更改,必须处理 DataGridView.CurrentCellDirtyStateChanged 事件。在处理程序中,如果当前单元格是复选框单元格,请调用 DataGridView.CommitEdit 方法并传入 Commit 值。

这是我用来获取无线电行为的代码:

    void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        // Manually raise the CellValueChanged event
        // by calling the CommitEdit method.
        if (dataGridView1.IsCurrentCellDirty)
        {
            dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }
    public void dataGridView1_CellValueChanged(object sender,
                                               DataGridViewCellEventArgs e)
    {
        // If a check box cell is clicked, this event handler sets the value
        // of a few other checkboxes in the same row as the clicked cell.
        if (e.RowIndex < 0) return; // row is sometimes negative?
        int ix = e.ColumnIndex;
        if (ix>=1 && ix<=3)
        {
            var row = dataGridView1.Rows[e.RowIndex];
            DataGridViewCheckBoxCell checkCell =
                (DataGridViewCheckBoxCell) row.Cells[ix];
            bool isChecked = (Boolean)checkCell.Value;
            if (isChecked)
            {
                // Only turn off other checkboxes if this one is ON. 
                // It's ok for all of them to be OFF simultaneously.
                for (int i=1; i <= 3; i++)
                {
                    if (i != ix)
                    {
                        ((DataGridViewCheckBoxCell) row.Cells[i]).Value = false;
                    }
                }
            }
            dataGridView1.Invalidate();
        }
    }

你想要的是DGV本身的CellContentClick。附加一个处理程序,用于检查 DGV 的该列是否为 CheckBoxCell,如果是,请取消选中该行上的所有其他复选框。

请注意,对于 CheckBoxCell,此事件在复选框值实际更改之前触发。这意味着,无论您对当前单元格执行什么操作,它都将被稍后触发的事件覆盖。摆脱这种情况的行为是,您可以通过选中行上的一个框然后再次选中它来不选中行上的任何单元格(无论您是否尝试在处理程序中设置复选框值,复选框将在第二次单击后最终清除(。要克服这个问题并强制选中其中一个复选框,您可以改为处理 CellValueChanged,如果更改的单元格是当前单元格并且未选中,请选中它。

  private void dataGridViewProduit_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        if ((sender as DataGridView).CurrentCell is DataGridViewCheckBoxCell)
        {
            if (Convert.ToBoolean(((sender as DataGridView).CurrentCell as DataGridViewCheckBoxCell).Value))
            {
                foreach (DataGridViewRow row in (sender as DataGridView).Rows)
                {
                    if (row.Index != (sender as DataGridView).CurrentCell.RowIndex && Convert.ToBoolean(row.Cells[e.ColumnIndex].Value) == true)
                    {
                        row.Cells[e.ColumnIndex].Value = false;
                    }
                }
            }
        }
    }
    private void dataGridViewClient_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (this.dataGridViewClient.IsCurrentCellDirty)
        {
            dataGridViewClient.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }

这里太容易了:

检查复选框列是数据网格视图中的第二列。

private void YourDatagridview_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
         if (IsHandleCreated)
        {
            if (YourDatagridview.CurrentCell == YourDatagridview.Rows[e.RowIndex].Cells[1])
            {
                if (Convert.ToBoolean(YourDatagridview.CurrentCell.Value) == true)
                {
                    for (int i = 0; i < YourDatagridview.RowCount; i++)
                    {
                        if (YourDatagridview.Rows[i].Cells[1] != YourDatagridview.CurrentCell)
                        {
                            YourDatagridview.Rows[i].Cells[1].Value = false;
                        }
                    }
                }
            }
        }
    }

也叫这个:

private void YourDatagridview_CurrentCellDirtyStateChanged(object sender, EventArgs e)
    {
        if (this.YourDatagridview.IsCurrentCellDirty)
        {
            YourDatagridview.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }

瞧!!