vb.net Code:
  1. Imports System.Drawing
  2. Imports System.Windows.Forms.VisualStyles
  3.  
  4. Public Class CheckBoxColumn
  5.     Inherits Windows.Forms.DataGridViewCheckBoxColumn
  6.  
  7.     Sub New()
  8.         Me.CellTemplate = New CheckBoxCell
  9.     End Sub
  10. End Class
  11.  
  12. Public Class TextBoxColumn
  13.     Inherits Windows.Forms.DataGridViewTextBoxColumn
  14.  
  15.     Sub New()
  16.         Me.CellTemplate = New TextBoxCell
  17.     End Sub
  18. End Class
  19.  
  20. Public Class TextBoxCell
  21.     Inherits Windows.Forms.DataGridViewTextBoxCell
  22.  
  23.     Public Overrides Function AdjustCellBorderStyle( _
  24.             ByVal dataGridViewAdvancedBorderStyleInput As Windows.Forms.DataGridViewAdvancedBorderStyle, _
  25.             ByVal dataGridViewAdvancedBorderStylePlaceHolder As Windows.Forms.DataGridViewAdvancedBorderStyle, _
  26.             ByVal singleVerticalBorderAdded As Boolean, _
  27.             ByVal singleHorizontalBorderAdded As Boolean, _
  28.             ByVal firstVisibleColumn As Boolean, _
  29.             ByVal firstVisibleRow As Boolean) As Windows.Forms.DataGridViewAdvancedBorderStyle
  30.  
  31.         ' Customize the top border of cells in the first row and the  
  32.         ' right border of cells in the first column. Use the input style  
  33.         ' for all other borders.
  34.  
  35.         With dataGridViewAdvancedBorderStylePlaceHolder
  36.  
  37.             If firstVisibleColumn Then
  38.                 .Left = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  39.             Else
  40.                 .Left = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  41.             End If
  42.  
  43.             If firstVisibleRow Then
  44.                 .Top = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  45.             Else
  46.                 .Top = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  47.             End If
  48.  
  49.             If Me.ColumnIndex = DataGridView.DisplayedColumnCount(False) - 1 Then
  50.                 .Right = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  51.             Else
  52.                 .Right = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  53.             End If
  54.  
  55.             If RowIndex = DataGridView.FirstDisplayedCell.RowIndex + DataGridView.DisplayedRowCount(False) - 1 Then
  56.                 .Bottom = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  57.             Else
  58.                 .Bottom = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  59.             End If
  60.  
  61.             ' .Right = dataGridViewAdvancedBorderStyleInput.Right
  62.             ' .Bottom = dataGridViewAdvancedBorderStyleInput.Bottom
  63.         End With
  64.  
  65.         Return dataGridViewAdvancedBorderStylePlaceHolder
  66.     End Function
  67.  
  68.     'Protected Overrides Sub Paint(graphics As Drawing.Graphics, clipBounds As Drawing.Rectangle, cellBounds As Drawing.Rectangle, rowIndex As Integer, elementState As Windows.Forms.DataGridViewElementStates, value As Object, formattedValue As Object, errorText As String, cellStyle As Windows.Forms.DataGridViewCellStyle, advancedBorderStyle As Windows.Forms.DataGridViewAdvancedBorderStyle, paintParts As Windows.Forms.DataGridViewPaintParts)
  69.     '    MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
  70.  
  71.     '    ' Draw Background
  72.     '    If (paintParts And Windows.Forms.DataGridViewPaintParts.SelectionBackground) = Windows.Forms.DataGridViewPaintParts.SelectionBackground Then
  73.     '        If rowIndex = DataGridView.CurrentRow.Index AndAlso DataGridView.SelectionMode = Windows.Forms.DataGridViewSelectionMode.FullRowSelect Then
  74.     '            Using cellBackground As New SolidBrush(cellStyle.SelectionBackColor)
  75.     '                graphics.FillRectangle(cellBackground, cellBounds)
  76.     '            End Using
  77.     '        Else
  78.     '            Using cellBackground As New SolidBrush(cellStyle.BackColor)
  79.     '                graphics.FillRectangle(cellBackground, cellBounds)
  80.     '            End Using
  81.     '        End If
  82.     '    End If
  83.  
  84.     '    ' Draw Borders
  85.     '    If (paintParts And Windows.Forms.DataGridViewPaintParts.Border) = Windows.Forms.DataGridViewPaintParts.Border Then
  86.     '        With advancedBorderStyle
  87.     '            ' .All = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  88.  
  89.     '            'If rowIndex = DataGridView.FirstDisplayedCell.RowIndex Then
  90.     '            '    .Top = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  91.     '            'End If
  92.  
  93.     '            If Me.ColumnIndex = DataGridView.FirstDisplayedCell.ColumnIndex Then
  94.     '                .Left = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  95.     '            Else
  96.     '                .Left = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  97.     '            End If
  98.  
  99.     '            If Me.ColumnIndex = DataGridView.DisplayedColumnCount(False) - 1 Then
  100.     '                .Right = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  101.     '            Else
  102.     '                .Right = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  103.     '            End If
  104.  
  105.     '            If cellBounds.X + cellBounds.Width = clipBounds.Width Then
  106.  
  107.     '            End If
  108.  
  109.     '            If rowIndex = DataGridView.FirstDisplayedCell.RowIndex + DataGridView.DisplayedRowCount(False) - 1 Then
  110.     '                .Bottom = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  111.     '            Else
  112.     '                .Bottom = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  113.     '            End If
  114.     '        End With
  115.  
  116.     '        PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle)
  117.     '    End If
  118.  
  119.     'End Sub
  120.  
  121. End Class
  122.  
  123. Public Class CheckBoxCell
  124.  
  125.     'Public Overrides Function AdjustCellBorderStyle( _
  126.     '        ByVal dataGridViewAdvancedBorderStyleInput As Windows.Forms.DataGridViewAdvancedBorderStyle, _
  127.     '        ByVal dataGridViewAdvancedBorderStylePlaceHolder As Windows.Forms.DataGridViewAdvancedBorderStyle, _
  128.     '        ByVal singleVerticalBorderAdded As Boolean, _
  129.     '        ByVal singleHorizontalBorderAdded As Boolean, _
  130.     '        ByVal firstVisibleColumn As Boolean, _
  131.     '        ByVal firstVisibleRow As Boolean) As Windows.Forms.DataGridViewAdvancedBorderStyle
  132.  
  133.     '    ' Customize the top border of cells in the first row and the  
  134.     '    ' right border of cells in the first column. Use the input style  
  135.     '    ' for all other borders.
  136.     '    If firstVisibleColumn Then
  137.     '        dataGridViewAdvancedBorderStylePlaceHolder.Left = _
  138.     '           Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  139.     '    Else
  140.     '        dataGridViewAdvancedBorderStylePlaceHolder.Left = dataGridViewAdvancedBorderStyleInput.Left
  141.     '    End If
  142.  
  143.     '    If firstVisibleRow Then
  144.     '        dataGridViewAdvancedBorderStylePlaceHolder.Top = _
  145.     '           Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  146.     '    Else
  147.     '        dataGridViewAdvancedBorderStylePlaceHolder.Top = dataGridViewAdvancedBorderStyleInput.Top
  148.     '    End If
  149.  
  150.     '    With dataGridViewAdvancedBorderStylePlaceHolder
  151.  
  152.     '        .Right = dataGridViewAdvancedBorderStyleInput.Right
  153.     '        .Bottom = dataGridViewAdvancedBorderStyleInput.Bottom
  154.     '    End With
  155.  
  156.     '    Return dataGridViewAdvancedBorderStylePlaceHolder
  157.     'End Function
  158.  
  159.     Protected Overrides Function GetFormattedValue(value As Object, rowIndex As Integer, ByRef cellStyle As Windows.Forms.DataGridViewCellStyle, valueTypeConverter As ComponentModel.TypeConverter, formattedValueTypeConverter As ComponentModel.TypeConverter, context As Windows.Forms.DataGridViewDataErrorContexts) As Object
  160.         Return If(Me.Value Is Nothing OrElse Not Convert.ToBoolean(Me.Value), False, Convert.ToBoolean(Me.Value))
  161.     End Function
  162.  
  163.     Protected Overrides Sub Paint(graphics As Drawing.Graphics, clipBounds As Drawing.Rectangle, cellBounds As Drawing.Rectangle, rowIndex As Integer, elementState As Windows.Forms.DataGridViewElementStates, value As Object, formattedValue As Object, errorText As String, cellStyle As Windows.Forms.DataGridViewCellStyle, advancedBorderStyle As Windows.Forms.DataGridViewAdvancedBorderStyle, paintParts As Windows.Forms.DataGridViewPaintParts)
  164.         MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
  165.  
  166.         Dim x As Int32 = CInt(cellBounds.Width / 2 - 8)
  167.         Dim y As Int32 = CInt(cellBounds.Height / 2 - 8)
  168.  
  169.         With graphics
  170.  
  171.             ' Draw Background
  172.             If (paintParts And Windows.Forms.DataGridViewPaintParts.SelectionBackground) = Windows.Forms.DataGridViewPaintParts.SelectionBackground Then
  173.                 If rowIndex = DataGridView.CurrentRow.Index AndAlso DataGridView.SelectionMode = Windows.Forms.DataGridViewSelectionMode.FullRowSelect Then
  174.                     Using cellBackground As New SolidBrush(cellStyle.SelectionBackColor)
  175.                         graphics.FillRectangle(cellBackground, cellBounds)
  176.                     End Using
  177.                 Else
  178.                     Using cellBackground As New SolidBrush(cellStyle.BackColor)
  179.                         graphics.FillRectangle(cellBackground, cellBounds)
  180.                     End Using
  181.                 End If
  182.             End If
  183.  
  184.             ' Draw Borders
  185.             If (paintParts And Windows.Forms.DataGridViewPaintParts.Border) = Windows.Forms.DataGridViewPaintParts.Border Then
  186.                 With advancedBorderStyle
  187.                     ' .All = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  188.  
  189.                     'If rowIndex = DataGridView.FirstDisplayedCell.RowIndex Then
  190.                     '    .Top = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  191.                     'End If
  192.  
  193.                     If Me.ColumnIndex = DataGridView.FirstDisplayedCell.ColumnIndex Then
  194.                         .Left = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  195.                     Else
  196.                         .Left = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  197.                     End If
  198.  
  199.                     If Me.ColumnIndex = DataGridView.DisplayedColumnCount(False) - 1 Then
  200.                         .Right = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  201.                     Else
  202.                         .Right = Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  203.                     End If
  204.  
  205.                     If cellBounds.X + cellBounds.Width = clipBounds.Width Then
  206.  
  207.                     End If
  208.  
  209.                     'If rowIndex = DataGridView.FirstDisplayedCell.RowIndex + DataGridView.DisplayedRowCount(False) - 1 Then
  210.                     '    .Bottom = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  211.                     'End If
  212.  
  213.                     If cellBounds.Y + 1 <> clipBounds.Height Then
  214.  
  215.                     End If
  216.                 End With
  217.  
  218.                 PaintBorder(graphics, clipBounds, cellBounds, cellStyle, advancedBorderStyle)
  219.             End If
  220.  
  221.             ' CheckBox
  222.             Using cellBackground As New SolidBrush(cellStyle.BackColor)
  223.                 graphics.FillRectangle(cellBackground, x + cellBounds.X, y + cellBounds.Y, 15, 15)
  224.             End Using
  225.  
  226.             checkBrush.Color = Me.DataGridView.RowsDefaultCellStyle.ForeColor
  227.             checkPen.Color = Me.DataGridView.GridColor
  228.  
  229.             .DrawRectangle(checkPen, x + cellBounds.X, y + cellBounds.Y, 15, 15)
  230.  
  231.             ' Check State
  232.             If CBool(EditedFormattedValue) = True Then
  233.                 .DrawString("✓", checkFont, checkBrush, New Point(x + cellBounds.X, y + cellBounds.Y))
  234.             End If
  235.  
  236.         End With
  237.  
  238.     End Sub
  239.  
  240.     Private checkFont As New Font("Segoe UI", 9, FontStyle.Bold)
  241.     Private checkBrush As New SolidBrush(Color.Black)
  242.     Private checkPen As New Pen(Color.Black, 1)
  243.  
  244.     Sub New()
  245.  
  246.         ' This call is required by the designer.
  247.         InitializeComponent()
  248.  
  249.         ' Add any initialization after the InitializeComponent() call.
  250.  
  251.     End Sub
  252.  
  253.  
  254.  
  255. End Class
  256.  
  257. Public Class DataGridViewCustomRow
  258.     Inherits Windows.Forms.DataGridViewRow
  259.  
  260.     Public Overrides Function AdjustRowHeaderBorderStyle( _
  261.         ByVal dataGridViewAdvancedBorderStyleInput As Windows.Forms.DataGridViewAdvancedBorderStyle, _
  262.         ByVal dataGridViewAdvancedBorderStylePlaceHolder As Windows.Forms.DataGridViewAdvancedBorderStyle, _
  263.         ByVal singleVerticalBorderAdded As Boolean, _
  264.         ByVal singleHorizontalBorderAdded As Boolean, _
  265.         ByVal isFirstDisplayedRow As Boolean, _
  266.         ByVal isLastDisplayedRow As Boolean) As Windows.Forms.DataGridViewAdvancedBorderStyle
  267.  
  268.         ' Customize the top border of the first row header and the
  269.         ' right border of all the row headers. Use the input style for  
  270.         ' all other borders.
  271.         If isFirstDisplayedRow Then
  272.             dataGridViewAdvancedBorderStylePlaceHolder.Top = _
  273.                 Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  274.         Else
  275.             dataGridViewAdvancedBorderStylePlaceHolder.Top = _
  276.                 Windows.Forms.DataGridViewAdvancedCellBorderStyle.None
  277.         End If
  278.  
  279.         With dataGridViewAdvancedBorderStylePlaceHolder
  280.             .Right = Windows.Forms.DataGridViewAdvancedCellBorderStyle.Single
  281.             .Left = dataGridViewAdvancedBorderStyleInput.Left
  282.             .Bottom = dataGridViewAdvancedBorderStyleInput.Bottom
  283.         End With
  284.  
  285.         Return dataGridViewAdvancedBorderStylePlaceHolder
  286.     End Function
  287. End Class

This is the code I have been fiddling with. The DataGridView I am using is double-buffered, if that matters. Maybe I am going about it all wrong.

The problem:
The borders that get drawn on the bottom of the last visible row flicker when I scroll the DataGridView. None of the other borders flicker.

What I want:
I want to be able to specify which borders get drawn, without flickering.

What I have tried:
Different versions of the above code. I have also placed a Refresh command in the scroll event of the DataGridView. This was needed so that all the cells actually get redrawn.

Should I be using the CellPainting event? Maybe some other method?