Personally I wouldn't use the
CellEnter
or
CellLeave
events - the user could just be tabbing through the cells without intending to edit them.
I would use the
CellBeginEdit
and
CellEndEdit
events instead. Something like this might work (although you might want to do a little more checking for null references). Note I've assumed the Checkbox column is column
0
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 0)
{
return;
}
if(string.IsNullOrEmpty((dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]).EditedFormattedValue.ToString()))
{
var cb = (dataGridView1.Rows[e.RowIndex].Cells[0]) as DataGridViewCheckBoxCell;
cb.Value = false;
}
}
private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if (e.ColumnIndex == 0)
{
return;
}
var cb =((DataGridViewCheckBoxCell)(dataGridView1.Rows[e.RowIndex].Cells[0])).Value;
if(cb == null || !(bool)cb)
{
e.Cancel = true;
}
}
There is a "gotcha" when using
CellContentClick
to capture the setting on/off of the Checkbox - If you look at this code snippet
var a = ((dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]) as DataGridViewCheckBoxCell).EditedFormattedValue;
var b = ((dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]) as DataGridViewCheckBoxCell).Value;
var c = ((dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]) as DataGridViewCheckBoxCell).FormattedValue;
Debug.Print("a{0}, b{1}, c{2}", a, b, c);
You get the following output when you first click on the Checkbox:
aTrue, b, cFalse
In other words we need to use
EditedFormattedValue
to get the value that we are moving
to
To prevent editing of the cells you can use the
ReadOnly
property of the cells BUT you need to handle the situation of the user trying to edit columns on a new row without ticking the box - the easiest way is just to check the value of the Checkbox in the
CellBeginEdit
event as I did above. Note in that case we need to use the
Value
property of the cell.
To automatically set the focus to the next column you use the
CurrentCell
property of the DataGridView. So this might work:
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex != 0)
{
return;
}
var z = (bool)((dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]) as DataGridViewCheckBoxCell).EditedFormattedValue;
for (var i = 1; i < dataGridView1.Columns.Count; i++)
{
dataGridView1.Rows[e.RowIndex].Cells[i].ReadOnly = !z;
}
if (!z)
{
return;
}
dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[1];
}
Down to your final requirement
Quote:
if cell while leaving is not empty it has to store the data of that row in database
It's a PITA to work out what you are trying to do with so much commented out code, so consider the following points.
You need to make sure that whatever the user has entered is valid, so the
CellLeave
,
CellValidating
and
RowValidating
are
not appropriate methods in which to put your database save code. Instead consider the following:
private void dataGridView1_CellValidated(object sender, DataGridViewCellEventArgs e)
{
}
private void dataGridView1_RowValidated(object sender, DataGridViewCellEventArgs e)
{
}
private void dataGridView1_Validated(object sender, EventArgs e)
{
}
private void btnSaveChanges_Click(object sender, EventArgs e)
{
}