0
votes

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)
        {}
    }
1
It looks like you delegate all your rendering efforts to the CellPainting event. IMO, when the rendering is related to the Rows, you should use the RowPrePaint/RowPostPaint events. Or create custom Columns/Cells and modify their styles using the DataGridViewAdvancedBorderStyle.Jimi
@Jimi I have tried putting it in the RowPostPaint event, but it yields the same result. When I put it in the RowPrePaint event, everything is a mess. I have also yesterday and today read up on DataGridViewAdvancedBorderStyle and the first answer I got was that it is not the way to do it, and I stopped pursuing that option. I have however just found a proper answer on it, and it does seem worth giving it a try, it will even streamline my code a lot. I will give it try and post my results. Thanks for the suggestions, it always helps if someone can make you think into a different direction.Bazïnga
I'd like to see the post where it's stated that the use of DataGridViewAdvancedBorderStyle 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
Ironically it was a post on StackOverflow where the dev wanted to change cells programatically while loading the grid. I think the use differs from the new sample I found. I will try and find it agaiin and post the link.Bazïnga

1 Answers

0
votes

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();   
}