I have a list of car objects that have a property called "Marked" that it's type is boolean. I want to check / uncheck this property, select only one of them, ie only one car can be selected from this list and at the same time I want the value true or The false of this property should be update in the bank.
exmple table:
Car Name | Marked |
---|---|
a | |
b |
problem is i can't check state of datagridviewcheckboxcolumn/cell
.for example i try blow codes but they don't working.
examlpe 1 :
DataGridViewCheckBoxCell dataGridViewCheckBoxCell = DataGridView1.Rows[e.RowIndex].Cells["Marked"] as DataGridViewCheckBoxCell;
if(Convert.ToBoolean(dataGridViewCheckBoxCell.Value) == true)
{
//some code
}
else if(Convert.ToBoolean(dataGridViewCheckBoxCell.Value) == false)
{
//some code
}
exmple 2 :
foreach (DataGridViewRow row in DataGridView1.Rows)
{
DataGridViewCheckBoxCell chk =(DataGridViewCheckBoxCell)row.Cells["Marked"];
if (chk.Value == chk.TrueValue)
{
chk.Value = chk.FalseValue;
}
else
{
chk.Value = chk.TrueValue;
}
}
how can i do it?
CodePudding user response:
It is unclear “where” the first code snippet is called from so I will focus on the second snippet of code.
One of the problems you will have comes from the if
statement…
if (chk.Value == chk.TrueValue) …
This condition chk.Value == chk.TrueValue
may not throw an error, HOWEVER… this is checking two different OBJECTS… chk.Value
is an OBJECT as is chk.TrueValue
… so it makes sense that the two “different” OBJECTS would NEVER be equal.
One way to solve this is to simply “cast” those OBJECTS to bool
values like…
if ((bool)chk.Value == (bool)chk.TrueValue) {…
HOWEVER the above line of code will ONLY work “IF”… the check box columns TrueValue
AND FalseValue
properties have been SET like…
CheckBoxColumn.TrueValue = true;
CheckBoxColumn.FalseValue = false;
IF you have NOT set the Check box column’s two properties TrueValue
AND FalseValue
like above… then the Check box columns TrueValue
and FalseValue
will be null
and this will cause the line of code … if ((bool)chk.Value == (bool)chk.TrueValue) …
to throw an exception since chk.TrueValue
is null
and the cast to a bool
will throw a null
exception.
Therefore, if you DO SET the Check box columns TrueValue
and FalseValue
then you will have to “cast” the objects to bool
values in order for the comparison to work as shown above.
Given all this… you may want to re-consider using the Check box columns TrueValue
and FalseValue
as the intended purpose of those properties is to allow you to “change” the actual true
and false
values to something else that is not necessarily a true
or false
value.
It is unimportant how you would use these properties in that context as it appears very clear that in this context… setting the Check box columns TrueValue
and FalseValue
properties to true
and false
is somewhat superfluous and creates more work for you.
So in this case, I suggest you completely drop using the Check box columns TrueValue
and FalseValue
properties.
If you want to ensure that only ONE check box is checked in the column… then you could wire up the grids CellContentClick
event. If the check box value changed, then simply “uncheck” all the cells in that column. Crude yes, but it should work.
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) {
if (dataGridView1.Columns[e.ColumnIndex].Name == "Marked") {
foreach (DataGridViewRow row in dataGridView1.Rows) {
if (!row.IsNewRow) {
row.Cells["Marked"].Value = false;
}
}
}
}
I hope this makes sense and helps.
CodePudding user response:
You can handle the CellContentClick
(or CellClick
) events of your DataGridView to handle the state of a DataGridViewCheckBoxCell
that should be a single choice (hence behaving as a RadioButton).
Store the Cell object currently selected when the Cell meets the criteria (its OwningColumn is a DataGridViewCheckBoxColumn
named Marked
).
Change the state of this Cell if it's the one currently selected, or reset it back to false
if it's not.
In this case, set the current Cell to the one just selected and set its state to true
.
Then you don't need to loop all the Rows each time a CheckBox changes value.
If you need to, call [DataGridView].EndEdit()
to update the value immediately.
For example:
DataGridViewCheckBoxCell currentCheckBoxCell = null;
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0) return;
var dgv = sender as DataGridView;
if (dgv[e.ColumnIndex, e.RowIndex] is DataGridViewCheckBoxCell cell &&
cell.OwningColumn.Name == "Marked")
{
if (currentCheckBoxCell is null) currentCheckBoxCell = cell;
if (cell == currentCheckBoxCell) {
cell.Value = !(bool)cell.Value;
}
else {
currentCheckBoxCell.Value = false;
currentCheckBoxCell = cell;
}
// Affects CellValueChanged
// dgv.EndEdit();
}
}
This is how it works: