"Mo"

Some notes on the FlowLayoutPanel

Published on

Some notes on the FlowLayoutPanel

Authors

I’ve been experimenting with the FlowLayoutPanel. There are a few catches to using it that can cause some confusion. In my case, the confusion came from anchoring and/or docking. I was dynamically adding some listviews to my panel to display results of data. There would be one to many listviews depending on the type of report the user requested. Having come from developing in ASP, it is still my first inclination to just create a table for each section and add it. The flow of the HTML would handle the rest. I figured I could get a FlowLayoutPanel and just add controls as needed and get similar functionality.

That was true to a degree; however, anchoring doesn’t perform as you might think. If you anchor to the left and right after setting the width, if there is only one control in the panel, it will drop down to a zero width. The actual behavior is that, if you anchor to the left and right, it will assume the width of the widest control already on the FlowLayoutPanel. The same is true if you set the Dock property to Fill. Check out this article on MSDN to see what I mean. The behavior also depends on the FlowDirection property.

Everything works great if your panel isn’t going to resize itself. You can just set the first control’s width to the width of the panel minus a few pixels and Dock.Fill everything else. If you want it to resize as you resize the form, though, it is looking like you’ll have to handle some layout events.

Here’s some code to get you started:

Public Class Form1
  Private WithEvents flowPanel As New FlowLayoutPanel()

  Public Sub New()
    ' This call is required by the Windows Form Designer.
    InitializeComponent()
    ' Add any initialization after the InitializeComponent() call.
    ' DON'T FORGET THESE LINES!
    flowPanel.Dock = DockStyle.Fill
    flowPanel.FlowDirection = FlowDirection.TopDown
    Me.Controls.Add(flowPanel)
    AddListView()
    AddListView()
  End Sub

  Private Sub AddListView()
    Dim totalList As New ListView()
    totalList.View = View.Details

    ' If first control, then set a width; otherwise, Dock.Fill it.
    If Me.flowPanel.Controls.Count > 0 Then
      totalList.Dock = DockStyle.Fill
    Else
      totalList.Width = Me.flowPanel.Width - 10
    End If

    totalList.Columns.AddRange(New ColumnHeader() _
      {GetColumnHeader("Col 1"), _
      GetColumnHeader("Col 2"), _
      GetColumnHeader("Col 3")})

    Dim item As ListViewItem = totalList.Items.Add("Row 1")
    item.SubItems.Add("1234.00")
    item.SubItems.Add("5678.00")
    item = totalList.Items.Add("Row 1")
    item.SubItems.Add("1234.00")
    item.SubItems.Add("5678.00")
    item = totalList.Items.Add("Row 1")
    item.SubItems.Add("1234.00")
    item.SubItems.Add("5678.00")

    Me.flowPanel.Controls.Add(totalList)
  End Sub

  Private Function GetColumnHeader(ByVal text As String) As ColumnHeader
    Dim col As New ColumnHeader()
    col.Text = text
    Return col
  End Function

  Private Sub flow_Layout(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.LayoutEventArgs) _
    Handles flowPanel.Layout

    Dim flowLayout As FlowLayoutPanel = DirectCast(sender, FlowLayoutPanel)
    If flowLayout.Controls.Count > 0 Then
      flowLayout.Controls(0).Width = flowLayout.Width - 10
    End If
  End Sub
End Class

Here’s MSDN another article that gives some basic information on the FlowLayoutPanel.