Vb.net 完成滚动后刷新绘制

Vb.net 完成滚动后刷新绘制,vb.net,winforms,scroll,datagridview,paint,Vb.net,Winforms,Scroll,Datagridview,Paint,我有一个datagridview,它在所选单元格周围放置一个黑色边框。我的代码工作正常,直到我在进行选择时滚动为止。当我在进行选择时向下滚动时,我的上边框消失了,这在此时不是问题,因为这表明有更多的选定单元格不在视图中,问题是一旦我进行了选择,然后返回到顶部,上边框就再也不会返回。我注意到在进入一个单元格时,dgv会重新绘制,我想这就是为什么我的上边框没有绘制的原因,因为它不在视图中,一旦我滚动回到顶部,我就不会输入任何新的单元格,所以上边框永远不会重新绘制 因此,我添加了一个滚动事件来刷新dg

我有一个datagridview,它在所选单元格周围放置一个黑色边框。我的代码工作正常,直到我在进行选择时滚动为止。当我在进行选择时向下滚动时,我的上边框消失了,这在此时不是问题,因为这表明有更多的选定单元格不在视图中,问题是一旦我进行了选择,然后返回到顶部,上边框就再也不会返回。我注意到在进入一个单元格时,dgv会重新绘制,我想这就是为什么我的上边框没有绘制的原因,因为它不在视图中,一旦我滚动回到顶部,我就不会输入任何新的单元格,所以上边框永远不会重新绘制

因此,我添加了一个滚动事件来刷新dgv绘制,但这似乎是先重新绘制,然后滚动,而不是滚动重新绘制,这会导致进一步选择的单元格边框不显示

所以我的问题是,有没有办法在卷轴完成后触发重新绘制

下面是我的代码,不确定它是否与显示相关,但它在这里

    Private Sub dgvdefault_paint(sender As Object, e As PaintEventArgs)
    With dgvdefault

        ' draw border around dgv
        e.Graphics.DrawRectangle(penborder, 0, 0, .Width - 1, .Height - 1)


        For Each cell In .SelectedCells

            ' get cell position and size

            a = cell.rowindex
            b = cell.columnindex

            Dim myrect As Rectangle = (.GetCellDisplayRectangle(b, a, False))
            Dim dgvdefault_headerrectangle As Rectangle = (.GetCellDisplayRectangle(-1, -1, False))

            ' top border

            If a = 0 Then
                e.Graphics.DrawLine(Pens.Black, myrect.X - 1, myrect.Y - 1, myrect.X - 1 + myrect.Width, myrect.Y - 1)
            ElseIf .Rows(a - 1).Cells(b).Selected = False Then
                e.Graphics.DrawLine(Pens.Black, myrect.X - 1, myrect.Y - 1, myrect.X - 1 + myrect.Width, myrect.Y - 1)
            End If

            ' bottom border

            If a = .RowCount - 1 Then
                e.Graphics.DrawLine(Pens.Black, myrect.X - 1, myrect.Y - 1 + myrect.Height, myrect.X - 1 + myrect.Width, myrect.Y - 1 + myrect.Height)
            ElseIf .Rows(a + 1).Cells(b).Selected = False Then
                e.Graphics.DrawLine(Pens.Black, myrect.X - 1, myrect.Y - 1 + myrect.Height, myrect.X - 1 + myrect.Width, myrect.Y - 1 + myrect.Height)
            End If

            ' left border

            If b = 0 Then
                e.Graphics.DrawLine(Pens.Black, myrect.X - 1, myrect.Y - 1, myrect.X - 1, myrect.Y - 1 + myrect.Height)
            ElseIf .Rows(a).Cells(b - 1).Selected = False Then
                e.Graphics.DrawLine(Pens.Black, myrect.X - 1, myrect.Y - 1, myrect.X - 1, myrect.Y - 1 + myrect.Height)
            End If

            ' right border

            If b = .ColumnCount - 1 Then
                e.Graphics.DrawLine(Pens.Black, myrect.X - 1 + myrect.Width, myrect.Y - 1, myrect.X - 1 + myrect.Width, myrect.Y - 1 + myrect.Height)
            ElseIf .Rows(a).Cells(b + 1).Selected = False Then
                e.Graphics.DrawLine(Pens.Black, myrect.X - 1 + myrect.Width, myrect.Y - 1, myrect.X - 1 + myrect.Width, myrect.Y - 1 + myrect.Height)
            End If

        Next

    End With

End Sub

Private Sub dgvdefault_scroll(sender As Object, e As ScrollEventArgs)

    dgvdefault.Refresh()

End Sub

ScrollEventArgs有一个可以在条件分支中计算的类型枚举

Edit*datagridview不会显示所有滚动事件类型,因此我们使用反射向内部组件事件添加侦听器

例如:

Option Strict On
Option Explicit On
Option Infer Off
Imports System.Reflection
Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        DataGridView1.ColumnCount = 10
        For i As Integer = 0 To 100
            Dim row As New DataGridViewRow
            DataGridView1.Rows.Add(row)
        Next
        DGVAddListener(DataGridView1)
    End Sub
    Public Function DGVAddListener(dataGridView As DataGridView) As Boolean
        Dim pInfo As PropertyInfo = dataGridView.GetType.GetProperty("VerticalScrollBar", BindingFlags.Instance Or BindingFlags.NonPublic)
        If pInfo Is Nothing Then Return False
        Dim dgvScrollBar As ScrollBar = CType(pInfo.GetValue(dataGridView, Nothing), ScrollBar)
        If dgvScrollBar is Nothing then Return False 
        AddHandler dgvScrollBar.Scroll, New ScrollEventHandler(AddressOf dgv_Scroll)
        Return True
    End Function
    Public Sub dgv_Scroll(sender As Object, e As ScrollEventArgs)
        Select Case e.Type
            Case ScrollEventType.EndScroll
                MsgBox("Scroll End!")
            Case ScrollEventType.First
            Case ScrollEventType.LargeDecrement
            Case ScrollEventType.LargeIncrement
            Case ScrollEventType.Last
            Case ScrollEventType.SmallDecrement
            Case ScrollEventType.SmallIncrement
            Case ScrollEventType.ThumbPosition
            Case ScrollEventType.ThumbTrack
        End Select
    End Sub
End Class

这并不是最好的答案,但这是我用来让我的dgv刷新后滚动的方法,看起来效果不错(延迟很小)


play with(播放):要正确显示,必须在滚动后触发
Paint
事件。否则,您将看不到正确的项目。您只是做得不正确。使用CellPaint事件。感谢Hans的回复,我没有使用CellPaint的原因是因为我假设我只能在特定单元格内绘制,而我的边框将在单元格外稍微绘制。不过,我现在要调查一下,看看我能不能让它发挥作用。谢谢保罗的回答,但我似乎无法让它发挥作用。我已经尝试过case scrolleventtype.endscroll msgbox(“scrollend”),如果e.Type=scrolleventtype.endscroll,那么msgbox(“scrollend”),但两种方法都不起作用。在无法实现这一点后,我上网,有人说endscroll不适用于DataGridView,但我不知道这是怎么回事。对我正在做的事情有什么建议吗?嗨,Jarron,我添加了一个修改,现在应该会引发EndScroll事件。我编辑了我的原始答案。我想没有办法为垂直和水平添加一个,所以如果你想同时捕获两个侦听器,你需要两个侦听器。将timer1.Interval更改为等于1,我看不到任何延迟。
Private Sub dgvdefault_scroll(sender As Object, e As ScrollEventArgs)
    AddHandler timer1.Tick, AddressOf timer1_tick
End Sub
Private Sub timer1_tick(sender As Object, e As EventArgs)
    dgvdefault.Refresh()
    RemoveHandler timer1.Tick, AddressOf timer1_tick
End Sub