Search code examples
c#winformsdatagridviewpaint

DataGridView Paint Event not drawing cell borders when scrolling from bottom to top


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.

grid_01

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.

grid_02

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)
        {}
    }

Solution

  • So after many different approaches and playing around, I have managed to get the borders to draw consistently using the code I originally posted in my question. I noticed that, when scrolling using the scrollbar and not the mouse, I got the same result. I added the code below, and it works, all the lines are drawn and are consistently displayed.

    private void data_grid_appointments_scroll(object sender, ScrollEventArgs e)
    {
        ((DataGridView)sender).Invalidate();   
    }