我有一个Windows窗体应用程序,它显示DataGridView中的对象列表。
此控件将bool值呈现为复选框。
对象属性中有一组三个相互排斥的复选框。最多其中一个可能是真的。因此,我希望复选框的行为类似于一组单选按钮。
老家伙的一个侧面评论:我认为这些天人们甚至不知道为什么这些被称为单选按钮。在过去,汽车中的收音机有4或5个按钮,按下任何一个按钮都会导致所有其他按钮弹出。它们是相互排斥的。 “单选按钮”现在可能不是一个有用的描述,因为无线电不再有这样的按钮,我不认为。
我该怎么办?我想如果我将“CheckedChanged”事件附加到复选框,我知道该行,我将能够找到所有其他复选框。
首次渲染时,我可以挂钩什么事件来抓住复选框控件,以便我可以将CheckedChanged事件附加到它?我知道DataGridView.CellFormatting
,但我认为这是错误的,因为每次DataGridView绘制时都会调用它。我真的需要一个仅在第一次呈现DGV时调用的事件。
答案 0 :(得分:7)
感谢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();
}
}
答案 1 :(得分:1)
你想要的就是DGV本身的CellContentClick。附加一个处理程序,检查DGV的那一列是否为CheckBoxCell,如果是,则取消选中该行上的所有其他复选框。
只是注意,对于CheckBoxCell,此事件在复选框值实际更改之前触发。这意味着无论您对当前单元格执行的操作如何,都将被稍后触发的事件覆盖。将摆脱这种情况的行为是,您可以检查行中没有单元格,方法是选中行上的一个框然后再次检查它(无论您是否尝试在处理程序中设置复选框值,第二次点击后,复选框将最终清除。要解决此问题并强制选中其中一个复选框,您可以改为处理CellValueChanged,如果更改的单元格是当前单元格并且未选中,请检查它。
答案 2 :(得分:1)
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);
}
}
答案 3 :(得分:0)
这里太容易了:
Conisder您的复选框列是数据网格视图中的第二列。
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);
}
}
和Voila !!