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:
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).
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.
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:
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:
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With