自动将列配合到Listview以用于垂直滚动条

我inheritance了Listview来执行一些小的更改,但我想改进usercontrol类或Form类中的任何地方的设计,因为我对Listview的默认大小调整机制不满意。

在Form Class中,我调整了最后一列(“Download”),如下所示:

ColumnDownload.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize) 

问题是当(默认)滚动条出现在列表视图中时,最后一列的大小不会自动固定/减小,因此水平和未嵌入的滚动条也会自动出现。

那么有人可以帮我解释一下如何在滚动条出现时自动修复最后一列的大小? 我很失落。

注意:我需要说我不是在寻找替代LV,比如ObjectListView

注意2 :我没有显示我的usercontrol类,因为我现在没有执行任何自动resize的改进,我不知道从哪里开始。

这是我的Listview正常:

在此处输入图像描述

这与填充项目的列表视图相同:

在此处输入图像描述

when the (default) scrollbar appears inside the listview the size of the last column is not automatically fixed/decreased …“默认滚动条”用于表示Veritical Scroll。

AutoResize不是AutoFit 。 它用于根据页眉文本范围或内容长度调整列的大小,而不是管理滚动条并且工作得很好。 如果它确实自动调整了最后一列的大小,那么当最后一列是一个小的“OK”时,我们会生气。 键入自动assembly时无法读取的列。

PInvokes在NativeMethods类中; 这些吃滚动条,并得到它们是否显示。

 Public Const WS_VSCROLL As Integer = &H200000 Public Const WS_HSCROLL As Integer = &H100000 Friend Enum SBOrientation As Integer SB_HORZ = &H0 SB_VERT = &H1 SB_CTL = &H2 SB_BOTH = &H3 End Enum  _ Private Shared Function ShowScrollBar(ByVal hWnd As IntPtr, ByVal wBar As Integer,  ByVal bShow As Boolean ) As  Boolean End Function  _ Private Shared Function GetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer End Function Friend Shared Function IsHScrollVisible(ByVal ctl As Control) As Boolean Dim wndStyle As Integer = GetWindowLong(ctl.Handle, GWL_STYLE) Return ((wndStyle And WS_HSCROLL) <> 0) End Function Friend Shared Function IsVScrollVisible(ByVal ctl As Control) As Boolean Dim wndStyle As Integer = GetWindowLong(ctl.Handle, GWL_STYLE) Return ((wndStyle And WS_VSCROLL) <> 0) End Function Friend Shared Sub ShowHideScrollBar(ByVal ctl As Control, ByVal sb As SBOrientation, ByVal bShow As Boolean) ShowScrollBar(ctl.Handle, sb, bShow) End Sub 

从最后一列中窃取xx像素; 如果VScroll消失,则将像素放回原位。

基本上会发生的事情是ClientSizeChanged触发两次:1)当VScroll到达时,然后在HScroll由于VScroll而到达时再次出现一些微观。 所以你必须处理两次事件。 这会在第一次传递中调整所需列的大小,并在第二次传递中使用HScroll。 即使在步骤1之后不再需要HScroll,如果您不手动删除它,它也会短暂显示。

如果由于您的布局方式或用户调整列的大小而需要HScroll,则无论如何都会调整最后一列的大小,但不要吃HScroll。 缺少检测何时不需要第一步的额外逻辑(您通常无法看到它执行此操作)。

注意事项:我不知道这将如何或是否适用于第三方主题。 我不认为主题可以修改这些内部滚动条。

此外, 这是用于子类LV ,我知道你已经做过。 对于其他人,通过对引用进行一些修改,这应该也可以在表单上使用相关事件(例如ClientSizeChanged )来“推送”更改,即使它在表单中留下了许多丑陋的代码。

这也不包含在IF AutoFit属性测试中。

 Private orgClient As Rectangle ' original client size for comparing Private _VScrollWidth As Integer Private _resizedCol As Integer = -1 Private _VScroll As Boolean = False ' persistent Scroll flags Private _HScroll As Boolean = False ' 3rd party??? _VScrollWidth = System.Windows.Forms.SystemInformation.VerticalScrollBarWidth 

把它放在像ISupportInitialize.EndInit这样的地方:

 orgClient = Me.ClientRectangle 

Sub New 不是 orgClient的好地方 – 尚未创建控件。 OnHandleCreated会这样做,但是没有ISupportInitialize ,我会在控件上调用一个新的Sub来代替Form_Load。 如果您想在手动调整列后再重新启动,那么这实际上很方便。 例如:

 ' method on subclassed LV: from form load: thisLV.ResetClientSize Public Sub ResetClientSize orgClient = Me.ClientRectangle End Sub 

 ' a helper: Private Function AllColumnsWidth() As Integer Dim w As Integer = 0 For Each c As ColumnHeader In Columns w += c.Width Next Return w End Function ' The Meat Protected Overrides Sub OnClientSizeChanged(ByVal e As System.EventArgs) Dim VScrollVis As Boolean Dim HScrollVis As Boolean ' get who is Now Showing...local vars VScrollVis = NativeMethods.IsVScrollVisible(Me) HScrollVis = NativeMethods.IsHScrollVisible(Me) ' width change Dim delta As Integer = (orgClient.Width - ClientRectangle.Width) Dim TotalWidth As Integer = AllColumnsWidth() If (TotalWidth < ClientRectangle.Width - _VScrollWidth) And (_resizedCol = -1) Then Exit Sub End If Me.SuspendLayout() ' If VScroll IS showing, but WASNT showing the last time thru here ' ... then we are here because VScroll just appeared. ' That being the case, trim the desired column If VScrollVis And _VScroll = False Then ' a smarter version finds the widest column and resizes THAT one _resizedCol = Columns.Count - 1 ' we have to wait for the HScroll to show up ' to remove it Columns(_resizedCol).Width -= (delta + 1) End If ' HScroll just appeared If HScrollVis And (delta = _VScrollWidth) Then ' HScroll popped up, see if it is needed If AllColumnsWidth() <= orgClient.Width Then ' no, go away foul beast ! NativeMethods.ShowHideScrollBar(Me, NativeMethods.SBOrientation.SB_HORZ, False) _HScroll = False ' hopefully ' allows us to set it back if the VScroll disappears orgClient = ClientRectangle Else ' ToDo: use this to detect when none of this is needed _HScroll = HScrollVis End If End If ' If VScroll ISNOT showing, but WAS showing the last time thru here ' ...then we are here because VScroll disappeared If VScrollVis = False And _VScroll = True Then ' put back the pixels If _resizedCol <> -1 Then Columns(_resizedCol).Width += (_VScrollWidth + 1) ' reset column tracker _resizedCol = -1 ' reset to new compare size orgClient = ClientRectangle End If End If _VScroll = VScrollVis Me.ResumeLayout() End Sub 

或多或少我已经完成了所以我会发布这个解决方案,代码仍然有问题’因为它在我试图“播放”显示和隐藏滚动条它可以挂起的某些情况下没有按预期工作listview,并确保代码有不必要的检查,可以改进,但现在我没有更多的时间来尝试修复相关的问题,如果有人可以帮助修复此代码,以改善它,那么谢谢你:

 Dim SizeAlreadyDecreased As Boolean = False Private Sub ElektroListView_Downloads_ClientSizeChanged(sender As Object, e As EventArgs) _ Handles ElektroListView_Downloads.ClientSizeChanged ' Retrieve all the column widths Dim AllColumnsWidth As Integer = (From col As ColumnHeader In CType(sender.Columns, ListView.ColumnHeaderCollection) Select col.Width).Sum ' Fix the last column width to fill the not-used blank space when resizing the Form. Me.ColumnDownload.Width = Me.ColumnDownload.Width + (sender.ClientSize.Width - AllColumnsWidth) - 2 ' Fix the last column width to increase or decrease the size if a VertivalScrollbar appears. If GetScrollbars(sender) AndAlso Not SizeAlreadyDecreased Then SizeAlreadyDecreased = True ColumnDownload.Width -= SystemInformation.VerticalScrollBarWidth ElseIf GetScrollbars(sender) AndAlso SizeAlreadyDecreased Then SizeAlreadyDecreased = True ElseIf Not GetScrollbars(sender) AndAlso SizeAlreadyDecreased Then SizeAlreadyDecreased = False ColumnDownload.Width += SystemInformation.VerticalScrollBarWidth ElseIf Not GetScrollbars(sender) AndAlso Not SizeAlreadyDecreased Then SizeAlreadyDecreased = False End If End Sub Private Const WS_VSCROLL As Integer = &H200000I Private Const WS_HSCROLL As Integer = &H100000I Private Const GWL_STYLE As Integer = -16I  Private Shared Function GetWindowLong( ByVal hWnd As HandleRef, ByVal nIndex As Integer ) As Integer End Function Public Function GetScrollbars(ByVal ctrl As Control) As ScrollBars Dim style As Integer = GetWindowLong(New HandleRef(ctrl, ctrl.Handle), GWL_STYLE) Dim HScroll As Boolean = ((style And WS_HSCROLL) = WS_HSCROLL) Dim VScroll As Boolean = ((style And WS_VSCROLL) = WS_VSCROLL) If (HScroll AndAlso VScroll) Then Return ScrollBars.Both ElseIf HScroll Then Return ScrollBars.Horizontal ElseIf VScroll Then Return ScrollBars.Vertical Else Return ScrollBars.None End If End Function