Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I prevent the vertical scrollbar from taking space in the control, causing an horizontal scrollbar?

I have a custom control with a FlowLayoutPanel embedded within, to which I add elements (other custom controls). In the layout event of the FlowLayoutPanel I resize all of the controls in the FlowLayoutPanel to the size of the containing FlowLayoutPanel.

This goes fine until a vertical scrollbar is needed (AutoScroll = True), taking space inside the FLpanel, causing an horizontal scrollbar to appear.

The gibberish you see is some random placeholder text that I generate in the element's constructor.

I would like to prevent this:

nasty scrollbar effect

I tried adding a vertical scroll control to the usercontrol and doing FlowLayoutPanel.VertScroll.Value=sender.value in the Scroll event: it seems to work, but makes the actual vertical and horizontal scrollbars flicker (appearing and disappearing) a lot when moving the scrollbar control.

I really don't know if there is some property to make the scrollbar external to the FlowLayoutPanel control contents.

I'm doing this in VB.Net, but C# answers are fine (as it is basically the same syntax, at least when working with controls & UI).

Edit


I forgot to mention that I have WrapContents=false and AutoScroll=true in the FlowLayoutPanel.

Also, if you think this design is familiar: it is a pixel-perfect copy of Opera M2's mail list screen.

Update 1


After your comments, I came up with this:

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

It seems to work, but there is a problem with the horizontal scrollbar showing up when the critical point at which the vertical scrollbar appears is reached.

Once another item is added the horizontal scrollbar vanishes.

Also, I thought that the problem could be caused by the ReorderControls sub not being called, so I made a button to call it, but nothing changed.

This problem is not present when removing elements (but it only occurs when adding).

It also occurs when the window is resized and the vertical scrollbar must appear.

As I show below, after a new element is added it works fine:

nasty scrollbar effect returns

Update 2


I have followed Plutonix's advise (adapting the code from his other answer), and so I have applied some modifications to the ReorderControls sub, in this way:

    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

Now the horizontal scrollbar flickers one time, instead of staying there, when the vertical one appears.

I like gifs, so here is the current effect:

nasty scrollbar effect: a new hope

As you probably can't see (due to the low frame rate of the gif), the horizontal bar is probably noticeable only to someone looking for it, for a fraction of second.

I consider the problem 80% solved, and will move on. If I or someone comes up with something definitive, I'll promptly accept the answer.

like image 539
beppe9000 Avatar asked Feb 09 '15 19:02

beppe9000


1 Answers

Here is an alternative approach that gives you your desired result. Granted it does NOT directly answer your question, but in my opinion, if you need to mess with the way controls work in order to get your desired solution, you are not using the correct controls.

Instead of adding your controls directly into a FowLayoutPanel,

Use a standard Panel object containing a TableLayoutPanel.

Set the Panel Properties to...

AutoScroll=True

Set the TableLayoutPanel properties to

Dock = Top

Autosize = True , GrowAndSHrink

Start out with just one cell in the TableLayoutPanel..

Now add your controls to the TableLayoutPanel...

e.g.

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

When the scrollbar appears the TableLAyoutPanel will shrink horizontally by the appropriate amount, and all the contained controls will also shrink automatically.

like image 177
Trevor_G Avatar answered Nov 17 '22 01:11

Trevor_G