I have an application in which one of my screens makes heavy use of DataGridViewCheckBoxCells
. In short, I have the table set up in VirtualMode
with an Undo system involved, validation, and so on. In some cases it doesn't make sense to check a box where another box is not first checked and so on. I let users do it, but I have a checking function that sets the cell's ErrorText
property and doesn't let them continue.
Blah, blah. I've already verified it's not my code clearing the ErrorText
or anything like that. The problem is DataGridViewCheckBoxCells
do not paint the error icon / glyph thingy when it is the current cell. I cannot reason why they were designed this way. Indeed the reference source (DataGridViewCheckBoxCell.cs) backs me up:
In DataGridViewCheckBoxCell.cs:
protected override Rectangle GetErrorIconBounds(Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
{
// some checks ...
Point ptCurrentCell = this.DataGridView.CurrentCellAddress;
if (ptCurrentCell.X == this.ColumnIndex &&
ptCurrentCell.Y == rowIndex && this.DataGridView.IsCurrentCellInEditMode)
{
// PaintPrivate does not paint the error icon if this is the current cell.
// So don't set the ErrorIconBounds either.
return Rectangle.Empty;
}
// behavior ...
}
and taking a look at DataGridViewCheckBoxCell.PaintPrivate
:
private Rectangle PaintPrivate(Graphics g,
Rectangle clipBounds,
Rectangle cellBounds,
int rowIndex,
DataGridViewElementStates elementState,
object formattedValue,
string errorText,
DataGridViewCellStyle cellStyle,
DataGridViewAdvancedBorderStyle advancedBorderStyle,
DataGridViewPaintParts paintParts,
bool computeContentBounds,
bool computeErrorIconBounds,
bool paint)
{
// blah blah
// here it determines "If I am the current cell DO NOT draw the error icon!"
Point ptCurrentCell = this.DataGridView.CurrentCellAddress;
if (ptCurrentCell.X == this.ColumnIndex &&
ptCurrentCell.Y == rowIndex && this.DataGridView.IsCurrentCellInEditMode)
{
drawErrorText = false;
}
// sure enough, drawErrorText must be true here for the error icon to be drawn
if (paint && DataGridViewCell.PaintErrorIcon(paintParts) && drawErrorText && this.DataGridView.ShowCellErrors)
{
PaintErrorIcon(g, cellStyle, rowIndex, cellBounds, errorBounds, errorText);
}
}
How can I get around this? I tried to subclass DataGridViewCheckBoxCell
to little avail. There are so many internal functions and constants I can't hit. I tried to hack it in the Form
that uses this table, and I managed to de-select the current cell if it is a DataGridViewCheckBoxCell
after its DirtyStateChanged
which I am intercepting anyway (for reasons). But this doesn't work--when a user selects a cell, sure enough, the error icon disappears. I can't intercept and block DataGridViewCheckBoxCell
s from being selected with SelectionChanged
, because selection is the first step in the process of editing a cell's value.
What can I do?