当我使用窗体右下角的调整大小手柄调整窗体大小时,它会触发用户控件的sizechanged事件。在用户控件内部,我有代码来设置水平滚动条的最大值和值。
如果我向右调整大小,则代码按预期工作。当我向左调整大小时,滚动的拇指变得非常大,滚动不能按预期工作。好像最大值被设置为一个较低的数字,但是我的Debug.WriteLine表明情况并非如此。实际上,当我慢慢地将表格调整为更窄时,它会在做正确和做错之间快速切换。
我很少处理滚动条,当我这样做时,它们总是很痛苦。是否有一位ScrollBar大师知道为什么会这样?我搜索了它并搜索了它,但我真的不知道该搜索什么。
这是我的代码。相关部分是从sizechanged事件处理程序调用的,它几乎是代码的底部。
Imports System.Reflection
Public Class Grid
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint Or ControlStyles.DoubleBuffer, True) 'Or ControlStyles.ResizeRedraw
End Sub
Private _FirstVisibleRow As Row
Private Property FirstVisibleRow As Row
Get
If _FirstVisibleRow Is Nothing And Rows.Any Then
_FirstVisibleRow = Rows.First
End If
Return _FirstVisibleRow
End Get
Set(value As Row)
_FirstVisibleRow = value
LastVisibleRow = GetLastVisibleRow()
End Set
End Property
Private _HeaderRow As Row
Public Property HeaderRow As Row
Get
If _HeaderRow Is Nothing Then
_HeaderRow = New Row(Me, RowHeight)
For Each Column As Column In Columns
_HeaderRow.Cells.Add(New Cell(Column, _HeaderRow))
Next
End If
Return _HeaderRow
End Get
Private Set(value As Row)
_HeaderRow = value
End Set
End Property
Private _LastVisibleRow As Row
Private Property LastVisibleRow As Row
Get
If _LastVisibleRow Is Nothing Then
_LastVisibleRow = GetLastVisibleRow()
End If
Return _LastVisibleRow
End Get
Set(value As Row)
_LastVisibleRow = value
End Set
End Property
Private _TotalColumnWidth As Integer
Friend Property TotalColumnWidth As Integer
Get
If _TotalColumnWidth = Nothing Then
_TotalColumnWidth = GetTotalColumnWidth()
End If
Return _TotalColumnWidth
End Get
Set(value As Integer)
_TotalColumnWidth = value
SetScrollBarVisibility()
End Set
End Property
Private _TotalRowHeight As Integer
Friend Property TotalRowHeight As Integer
Get
If _TotalRowHeight = Nothing Then
_TotalRowHeight = GetTotalRowHeight()
End If
Return _TotalRowHeight
End Get
Set(value As Integer)
_TotalRowHeight = value
SetScrollBarVisibility()
End Set
End Property
Private _VisibleGridSize As Size
Private Property VisibleGridSize As Size
Get
If _VisibleGridSize = Nothing Then
_VisibleGridSize = GetVisibleGridSize()
End If
Return _VisibleGridSize
End Get
Set(value As Size)
_VisibleGridSize = value
VisibleRowCount = GetVisibleRowCount()
SetScrollBarVisibility()
End Set
End Property
Private Sub SetScrollBarVisibility()
VScrollBar1.Bounds = New Rectangle(Width - VScrollBar1.Width, 0, VScrollBar1.Width, Height - IIf(HScrollBar1.Visible, HScrollBar1.Height, 0))
HScrollBar1.Bounds = New Rectangle(0, Height - HScrollBar1.Height, Width - IIf(VScrollBar1.Visible, VScrollBar1.Width, 0), HScrollBar1.Height)
VScrollBar1.Maximum = Math.Max(0, TotalRowHeight - Height - IIf(HScrollBar1.Visible, HScrollBar1.Height, 0))
HScrollBar1.Maximum = Math.Max(0, TotalColumnWidth - Width + IIf(VScrollBar1.Visible, VScrollBar1.Width, 0))
HScrollBar1.Value = 0
VScrollBar1.Visible = TotalRowHeight > VisibleGridSize.Height
HScrollBar1.Visible = TotalColumnWidth > VisibleGridSize.Width
Debug.WriteLine(String.Format("HScrollBar1.Minimum {0}, HScrollBar1.Maximum {1}, HScrollBar1.Value {2}", HScrollBar1.Minimum, HScrollBar1.Maximum, HScrollBar1.Value))
End Sub
Private _VisibleRowCount As Integer
Private Property VisibleRowCount As Integer
Get
If _VisibleRowCount = 0 Then
_VisibleRowCount = GetVisibleRowCount()
End If
Return _VisibleRowCount
End Get
Set(value As Integer)
_VisibleRowCount = value
LastVisibleRow = GetLastVisibleRow()
PageHeight = GetPageHeight()
End Set
End Property
Private Function GetLastVisibleRow() As Row
If Not Rows.Any Then Return Nothing
Return Rows(Math.Min(FirstVisibleRow.Index + VisibleRowCount - 1, Rows.Count - 1))
End Function
Private Function GetPageHeight() As Integer
Return RowHeight * GetVisibleRowCount()
End Function
Private Function GetRowHeight() As Integer
Return TextRenderer.MeasureText("X", Font).Height + 6
End Function
Private Function GetVisibleGridSize() As Size
Return New Size(Width - IIf(VScrollBar1.Visible, VScrollBar1.Width, 0),
Height - HeaderRow.Height - IIf(HScrollBar1.Visible, HScrollBar1.Height, 0)) 'don't count header row or horiz scroll bar
End Function
Private Function GetVisibleRowCount() As Integer
Return Math.Ceiling(VisibleGridSize.Height / RowHeight)
End Function
Public Shadows Sub Refresh()
ClearSelection()
_HeaderRow = Nothing
_Rows = Nothing
AutoSizeColumns()
TotalRowHeight = GetTotalRowHeight()
Invalidate()
End Sub
Friend Function GetTotalColumnWidth() As Integer
Return Columns.Select(Function(x) x.Width).Aggregate(0, Function(x, y) x + y)
End Function
Friend Function GetTotalRowHeight() As Integer
Return Rows.Select(Function(x) x.Height).Aggregate(0, Function(x, y) x + y)
End Function
Private Function VisibleRows() As List(Of Row)
Return Rows.Where(Function(x) x.Index >= FirstVisibleRow.Index AndAlso x.Index <= LastVisibleRow.Index).ToList
End Function
Private Sub Grid_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
e.Graphics.Clear(BackColor)
'e.ClipRectangle
Dim Left As Integer = -HScrollBar1.Value
For Each Column As Column In Columns
Left = Column.Draw(e.Graphics, Left)
Next
Dim Top As Integer = HeaderRow.Draw(e.Graphics)
For Each Row As Row In VisibleRows()
Top = Row.Draw(e.Graphics, Top)
Next
End Sub
Private Sub Grid_Scroll(sender As Object, e As System.Windows.Forms.ScrollEventArgs) Handles Me.Scroll
If e.ScrollOrientation = ScrollOrientation.VerticalScroll Then
Select Case e.Type
Case ScrollEventType.First
FirstVisibleRow = Rows.First
Case ScrollEventType.Last
FirstVisibleRow = Rows(Rows.Last.Index - VisibleRowCount + 1)
Case ScrollEventType.SmallDecrement
FirstVisibleRow = Rows(Math.Max(FirstVisibleRow.Index - 1, 0))
Case ScrollEventType.SmallIncrement
FirstVisibleRow = Rows(Math.Min(FirstVisibleRow.Index + 1, Rows.Last.Index - VisibleRowCount + 1))
Case ScrollEventType.LargeDecrement
FirstVisibleRow = Rows(Math.Max(FirstVisibleRow.Index - VisibleRowCount, 0))
Case ScrollEventType.LargeIncrement
FirstVisibleRow = Rows(Math.Min(LastVisibleRow.Index, Rows.Last.Index - VisibleRowCount + 1))
End Select
End If
Invalidate()
End Sub
Private Sub Grid_SizeChanged(sender As Object, e As System.EventArgs) Handles Me.SizeChanged
VisibleGridSize = GetVisibleGridSize()
End Sub
Private Sub HScrollBar1_Scroll(sender As Object, e As System.Windows.Forms.ScrollEventArgs) Handles HScrollBar1.Scroll
Invalidate()
End Sub
End Class
答案 0 :(得分:0)
我的AutoScroll
的{{1}}属性被父控件设置为UserControl
。一旦我在设计器中将其设置回False,我的代码就会100%按预期运行。