如何防止垂直滚动条占用控件中的空间,从而导致水平滚动条?

时间:2015-02-09 19:48:11

标签: c# .net vb.net winforms

我有一个嵌入了FlowLayoutPanel的自定义控件,我添加了元素(其他自定义控件)。在FlowLayoutPanel的布局事件中,我将FlowLayoutPanel中的所有控件调整为包含FlowLayoutPanel的大小。

直到需要垂直滚动条(AutoScroll = True),在FLpanel内占用空间,才会显示水平滚动条。

你看到的乱码是我在元素的构造函数中生成的一些随机占位符文本。

我想阻止这个:

nasty scrollbar effect

我尝试在用户控件中添加一个垂直滚动控件并在FlowLayoutPanel.VertScroll.Value=sender.value事件中执行Scroll:它似乎有用,但会使实际的垂直和水平滚动条闪烁(出现和消失)很多移动滚动条控件时。

我真的不知道是否有一些属性可以使滚动条位于FlowLayoutPanel控件内容的外部。

我在VB.Net中这样做,但C#答案很好(因为它基本上是相同的语法,至少在使用控件和UI时)。

修改


我忘了提及WrapContents=false中有AutoScroll=trueFlowLayoutPanel

另外,如果您认为这个设计很熟悉:它是Opera M2邮件列表屏幕的像素完美副本。

更新1


在您发表评论后,我想出了这个:

Public Class FlowListPanel ' The user control

Private Sub Me_Load(sender As Object, e As EventArgs) Handles Me.Load
    FL_Panel.AutoScroll = True ' FL_Panel is the FlowLayoutPanel
    FL_Panel.WrapContents = False

    FL_Panel.Dock = System.Windows.Forms.DockStyle.Fill
    FL_Panel.FlowDirection = System.Windows.Forms.FlowDirection.TopDown
    FL_Panel.Margin = New System.Windows.Forms.Padding(0)
End Sub

Sub AddItem(c As Control)
    FL_Panel.Controls.Add(c)
    ReorderControls()
End Sub

Private Sub FLP_CSC(sender As Object, e As EventArgs) Handles FL_Panel.ClientSizeChanged
    ReorderControls()
End Sub

Sub ReorderControls()
    For Each ctrl In FL_Panel.Controls
        ctrl.Width = FL_Panel.ClientSize.Width
    Next
End Sub

Private Sub FL_Panel_L(sender As Object, e As LayoutEventArgs) Handles FL_Panel.Layout
    ReorderControls()
End Sub

End Class

它似乎有效,但是当达到垂直滚动条的临界点时,水平滚动条出现问题。

添加其他项目后,水平滚动条会消失。

另外,我认为问题可能是由ReorderControls sub未被调用引起的,所以我做了一个按钮来调用它,但没有任何改变。

删除元素时不存在此问题(但仅在添加时才会出现)。

当调整窗口大小并且必须出现垂直滚动条时,也会发生这种情况。

如下所示,添加新元素后效果很好:

nasty scrollbar effect returns

更新2


我遵循了Plutonix的建议(调整代码from his other answer),因此我以这种方式对ReorderControls sub应用了一些修改:

    Sub ReorderControls()

    Dim HScrollVis As Boolean = NativeMethods.IsHScrollVisible(FL_Panel)

    If HScrollVis Then ' HScroll visible -> kill it with fire!
        NativeMethods.ShowHideScrollBar(FL_Panel,
                                        NativeMethods.SBOrientation.SB_HORZ,
                                        False)
        Return ' as it works anyway...
    End If

    For Each ctrl In FL_Panel.Controls
        ctrl.Width = FL_Panel.ClientSize.Width
    Next
    End Sub

现在水平滚动条闪烁一次,而不是停留在那里,当垂直滚动条出现时。

我喜欢GIF,所以这是当前效果:

nasty scrollbar effect: a new hope

正如你可能看不到的那样(由于gif的低帧速率),水平条可能只对寻找它的人有明显的影响,只需几分之一秒。

我认为问题80%已经解决,并将继续前进。如果我或某人想出了明确的内容,我会立即接受答案。

2 个答案:

答案 0 :(得分:2)

这是一种可以为您提供所需结果的替代方法。虽然它没有直接回答你的问题,但在我看来,如果你需要弄乱控制工作的方式以获得你想要的解决方案,你就没有使用正确的控制。

而不是将控件直接添加到FowLayoutPanel中,

使用包含TableLayoutPanel的标准Panel对象。

将面板属性设置为...

<强>自动滚动=真

将TableLayoutPanel属性设置为

Dock = Top

Autosize = True,GrowAndSHrink

从TableLayoutPanel中只有一个单元格开始..

现在将您的控件添加到TableLayoutPanel ...

e.g。

Dim CTRL As New Your_User_Control
TableLayoutPanel1.Controls.Add(CTRL)
CTRL.Dock = DockStyle.Top

当滚动条出现时,TableLAyoutPanel将水平缩小适当的数量,并且所有包含的控件也将自动缩小。

答案 1 :(得分:0)

请确保使用以下属性对其进行初始化:

this.WrapContents = false;
this.AutoScroll = true;

您还需要确保您添加的控件的最大宽度为控件宽度减去滚动条宽度。

应该这样做。


修改

我从我的一个自定义控件中获得了此解决方案。它似乎与this post非常相似 - 我最初可能从那里得到它,我无法记住。发布链接以防万一。


编辑2:

由于您已经设置了这些属性并查看了图像,因此您只需要将要添加到FlowPanel的控件缩小,或者将FlowPanel添加到更宽的范围内。

基本上,您只需要允许滚动条出现时占用的空间。您可以检测它是否可见并强制内部控件相应地更新其布局,如果您真的想要始终使用所有宽度。