Reputation: 131
I have a datagridview fill with data from database. The first column is a checkboxcolumn (data for this column retrieved from database is type BIT) and I want the user only check one. If the user select other one, the first one have to be unchecked.
I have seen a lot of code and none works.
What I could do?
Is a Winforms C# app with SQL SERVER.
Upvotes: 7
Views: 13373
Reputation: 1508
To handle dataGridView_CellValueChanged
event we must trigger dataGridView_CellContentClick
event (which does not have checkboxes current state) will call CommitEdit
. This will trigger dataGridView_CellValueChanged
event where we can write our logic to check/uncheck checkboxes.
private void dataGridView_CellContentClick(object sender,
DataGridViewCellEventArgs e)
{
dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
/// <summary>
/// This will be fired by CellContentClick event from above
/// </summary>
private void dataGridView_CellValueChanged(object sender,
DataGridViewCellEventArgs e)
{
//0 is checkbox column index
var columnIndex = 0;
if (e.ColumnIndex == columnIndex )
{
var isChecked = (bool)dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
if (isChecked)
{
foreach (DataGridViewRow row in dataGridView.Rows)
{
if (row.Index != e.RowIndex)
{
row.Cells[columnIndex].Value = !isChecked;
}
}
}
}
}
//Bind the events in the form designer
this.dataGridView.CellContentClick += new DataGridViewCellEventHandler(this.dataGridView_CellContentClick);
this.dataGridView.CellValueChanged += new DataGridViewCellEventHandler(this.dataGridView_CellValueChanged);
Upvotes: 0
Reputation: 170
Here is my answer based on data manipulation. You need a datagridview named DataGridView1 in the form and nothing else.
DataTable dt;
private void Form1_Load(object sender, EventArgs e)
{
dt = CreateDataTablePeople("People");
BindingSource bs = new BindingSource();
bs.DataSource = dt;
dataGridView1.DataSource = bs;
dt.ColumnChanging += Dt_ColumnChanging ;
}
private void Dt_ColumnChanging(object sender, DataColumnChangeEventArgs e)
{
if (e.Column.ColumnName == "Abilitato")
{
bool b = Convert.ToBoolean(e.ProposedValue);
if (!b)
{
e.ProposedValue = true;
return;
}
dt.ColumnChanging -= Dt_ColumnChanging;
for (int i = dt.Rows.Count - 1; i >= 0; i--)
{
if (dt.Rows[i]["Id"] != e.Row["Id"])
{
dt.Rows[i]["Abilitato"] = false;
dt.Rows[i].EndEdit();
}
}
dt.ColumnChanging += Dt_ColumnChanging;
}
}
private DataTable CreateDataTablePeople(string TableName)
{
using (DataTable dt = new DataTable(TableName))
{
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Abilitato", typeof(bool));
dt.LoadDataRow(new object[] { 1, "Frank", false }, true);
dt.LoadDataRow(new object[] { 2, "Michael", false}, true);
dt.LoadDataRow(new object[] { 3, "Paul", false }, true);
return dt;
}
}
private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
DataGridViewDataErrorContexts ec = DataGridViewDataErrorContexts.Commit;
DataGridView dg = (DataGridView)sender;
bool b = dg.CommitEdit(ec);
}
Upvotes: 0
Reputation: 2566
private void DataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
{
//Check to ensure that the row CheckBox is clicked.
if (e.RowIndex >= 0 && e.ColumnIndex == 0)
{
//Loop and uncheck all other CheckBoxes.
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Index == e.RowIndex)
{
row.Cells["checkBoxColumn"].Value = !Convert.ToBoolean(row.Cells["checkBoxColumn"].EditedFormattedValue);
}
else
{
row.Cells["checkBoxColumn"].Value = false;
}
}
}
}
Upvotes: 0
Reputation:
Here is a slightly cleaned-up version. My checkbox column is dynamically added and always the last column in the grid, but you get the idea:
private void ProfilesGrid_CellContentClick(object sender, [NotNull] DataGridViewCellEventArgs e)
{
DataGridView dataGridView = (DataGridView)sender;
int columnCount = dataGridView.Columns.GetColumnCount(DataGridViewElementStates.None) - 1;
if (e.ColumnIndex != columnCount)
{
return;
}
dataGridView.EndEdit();
if (!(bool) dataGridView[e.ColumnIndex, e.RowIndex].Value)
{
return;
}
foreach (DataGridViewRow row in dataGridView.Rows.Cast<DataGridViewRow>().Where(row => row.Index != e.RowIndex))
{
row.Cells[columnCount].Value = false;
}
}
Upvotes: 0
Reputation: 91
VB net version
Private Sub dataGridView_CellValueChanged(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DG_SubSyncs.CellValueChanged
Dim columnIndex As Integer = 0
If (e.ColumnIndex = columnIndex) Then
'If the user checked this box, then uncheck all the other rows
Dim isChecked As Boolean = CBool(DG_SubSyncs.Rows(e.RowIndex).Cells(e.ColumnIndex).Value)
If (isChecked) Then
For Each row In DG_SubSyncs.Rows
If (row.Index <> e.RowIndex) Then
row.Cells(columnIndex).Value = Not isChecked
End If
Next
End If
End If
End Sub
Upvotes: 0
Reputation: 995
Subscribe to CellContentClick
and add dataGridView.EndEdit()
for much better user experience (cell doesn't have to lose the focus for event to be fired):
private void ChangeCheckedStateOfOtherCheckboxesInDgv(object sender, DataGridViewCellEventArgs e)
{
const int chkBoxColumnIndex = 0;
var dataGridView = (DataGridView)sender;
if (e.ColumnIndex == chkBoxColumnIndex)
{
dataGridView.EndEdit();
var isChecked = (bool)dataGridView[e.ColumnIndex, e.RowIndex].Value;
if (isChecked)
{
foreach (DataGridViewRow row in dataGridView.Rows)
{
if (row.Index != e.RowIndex)
row.Cells[chkBoxColumnIndex].Value = !isChecked;
}
}
}
}
Upvotes: 2
Reputation: 2289
You have to set the VirtualMode setting to TRUE on the DGV to allow only one checkbox.
Upvotes: -1
Reputation: 3255
private void dataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
// Whatever index is your checkbox column
var columnIndex = 0;
if (e.ColumnIndex == columnIndex)
{
// If the user checked this box, then uncheck all the other rows
var isChecked = (bool)dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
if (isChecked)
{
foreach (DataGridViewRow row in dataGridView.Rows)
{
if (row.Index != e.RowIndex)
{
row.Cells[columnIndex].Value = !isChecked;
}
}
}
}
}
Upvotes: 4