Using C# WinForms, I have a docked (Fill) a standard DataGridView control on my form. The DataGridView columns and rows are created once, programaticallly, when the form is loads. I paint some header and cell borders in the Paint event. All is good.
The problem I have is scrolling. When I scroll down, everything paints fine. However, when I scroll back up, some of the borders are not painted. When the unpainted area is displayed on screen, and I scroll back down again while still keeping the unpainted area on screen, it repaints fine. I am battling to see anything strange when debugging because it happens completely random; one row could not be painted now, and next time round it could be a different border. "I know it paints fine" because when I scroll down right to the bottom, all the way down, everything is painted as it should. It is only when I scroll back up that random rows are not painted, and it could be different rows each time.
As you will see in the code below, I am setting the borders that I don't want painted to transparent. Even if I set the unpainted borders with to 0 and set the border style to none, it yields the same result.
Is this a GUI bug or a refresh bug or what?
As per example, I have scrolled down all the way, and on the way down I have seen that all the borders paint fine. I can redo it over and over with the same result, as below.
Then when I scroll back up, some borders are not painted, randomly, as you can see on the grid line with text 20:00; the row "20:00" should look the same as row "21:00", as can be seen below.
The code I am using to paint is:
/// <summary>data grid view cell painting event : to draw custom cell borders</summary>
private void dgv_cell_painting(object sender, DataGridViewCellPaintingEventArgs e)
{
try
{
int row = e.RowIndex;
int column = e.ColumnIndex;
int last_col = data_grid_appointments.ColumnCount - 1;
int last_row = data_grid_appointments.RowCount - 1;
string row_tag = ((DataGridView)sender).Rows[row].Tag.ToString();
bool is_hour = (string.IsNullOrEmpty(row_tag) ? false : row_tag.EndsWith("00"));
switch (row < last_row)
{
case true: //not the last row
switch (row == 0
||
is_hour)
{
case true: //first row or row is on the hour
switch (column == -1)
{
case true:
e.PaintBackground(e.CellBounds, true);
e.PaintContent(e.CellBounds);
ControlPaint.DrawBorder
(
e.Graphics
, e.CellBounds
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Orange, 1, ButtonBorderStyle.Solid
, Color.Orange, 1, ButtonBorderStyle.Solid
, Color.Transparent, 1, ButtonBorderStyle.Solid
);
e.Graphics.DrawString
(
row_tag.Substring(0, 2) + ":" + row_tag.Substring(2)
, e.CellStyle.Font
, new SolidBrush(Color.Black)
, e.CellBounds
, new StringFormat()
{
Alignment = StringAlignment.Center
,
FormatFlags = StringFormatFlags.NoWrap
,
LineAlignment = StringAlignment.Center
}
);
e.Handled = true;
break;
default:
switch (column == data_grid_appointments.ColumnCount - 1)
{
case true:
e.PaintBackground(e.CellBounds, true);
e.PaintContent(e.CellBounds);
ControlPaint.DrawBorder
(
e.Graphics
, e.CellBounds
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Orange, 1, ButtonBorderStyle.Solid
, Color.Orange, 1, ButtonBorderStyle.Solid
, Color.Transparent, 1, ButtonBorderStyle.Solid
);
e.Handled = true;
break;
default:
e.PaintBackground(e.CellBounds, true);
e.PaintContent(e.CellBounds);
ControlPaint.DrawBorder
(
e.Graphics
, e.CellBounds
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Orange, 1, ButtonBorderStyle.Solid
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Transparent, 1, ButtonBorderStyle.Solid
);
e.Handled = true;
break;
}
break;
}
break;
default: //not the first column
if (column == -1
||
column == data_grid_appointments.ColumnCount - 1)
{
e.PaintBackground(e.CellBounds, true);
e.PaintContent(e.CellBounds);
ControlPaint.DrawBorder
(
e.Graphics
, e.CellBounds
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Orange, 1, ButtonBorderStyle.Solid
, Color.Transparent, 1, ButtonBorderStyle.Solid
);
e.Handled = true;
}
break;
}
break;
default: //last row
switch (column == -1
||
column == last_col)
{
case true: //row header column OR very last column in the very last row
e.PaintBackground(e.CellBounds, true);
e.PaintContent(e.CellBounds);
ControlPaint.DrawBorder
(
e.Graphics
, e.CellBounds
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Orange, 1, ButtonBorderStyle.Solid
, Color.Orange, 1, ButtonBorderStyle.Solid
);
e.Handled = true;
break;
default: //not the header column
e.PaintBackground(e.CellBounds, true);
e.PaintContent(e.CellBounds);
ControlPaint.DrawBorder
(
e.Graphics
, e.CellBounds
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Transparent, 1, ButtonBorderStyle.Solid
, Color.Orange, 1, ButtonBorderStyle.Solid
);
e.Handled = true;
break;
}
break;
}
}
catch (Exception ex)
{}
}
RowPrePaint
/RowPostPaint
events. Or create custom Columns/Cells and modify their styles using the DataGridViewAdvancedBorderStyle. – JimiDataGridViewAdvancedBorderStyle
is not the way to do it (when the DataGridView control itself uses it. In fact, these are methods that you override to customize the Grid - the DataGridView itself, the DataGridViewColuumn or the DataGridViewCell, since the DGV can be customized to Cell level). – Jimi