(Print this page)

The Table and Flow Layout container controls
Published date: Sunday, January 17, 2010
On: Moer and Éric Moreau's web site

Everybody is crazy about the WPF Grid control and its powerful rendering of contained controls. Most of us forgot or simply aren’t aware of 2 controls that sit right into the toolbox for years now. I just named the TableLayoutPanel and the FlowLayoutPanel controls. These 2 controls (mainly the TableLayoutPanel control) provide many of the same features.


You will be happy to learn that you surely have everything you need. You are not required to install something else and you don’t even have to reference any new controls. These controls sit in the standard toolbox since Visual Studio 2005. So there is no reason not to use them.

Demo code

There is no code this month! Only a demonstration of using 2 interesting controls.

The FlowLayoutPanel control

This control repositions contained controls much like an HTML page would do. When the form is resized, the contained controls are not resized, they are reposition so that we can always see them completely. If a control does not fit on a line, it is automatically moved to the following line.

One funny thing when you start dragging and dropping controls into a FlowLayoutPanel is that it shows quite a different cursor where the controls you are currently dragging will be dropped. If you drop your new between 2 existing controls, you can see all other controls repositioning themselves to fit the container.

One sad thing is that the container control does not automatically provide a vertical scrollbar when the contained controls are not visible anymore. But if you set the AutoScroll property to True, a scrollbar appears when required.

A great property provided by this control is named FlowDirection. It lets you control the direction in which the contained are controls are positioned. By default, it is set to LeftToRight but you can also select one of its other values that are TopDown, RightToLeft, and BottomUp.

Sometime, you want to break the flow. For example, say the direction is LeftToRight and you want to force a control to appear on another line whatever other controls fits or not. To force this behaviour, select the last control you want to appear on a line and set its FlowBreak property to True.

Personally, I don’t like this control. It may just be that I haven’t found the right scenario to use it! I can’t imagine having a bunch of textboxes moving around when the screen size changes. But images or thumbnails might be well served with that kind of behaviour.

The TableLayoutPanel control

This control really behaves like a HTML table. When you add this control to a form, by default it contains 2 columns and 2 rows.

Figure 1: The TableLayoutPanel Common Tasks

When you add a TableLayoutPanel control to a form, the smarttag is displayed showing you the 5 most common tasks for this control (as shown in figure 1):

  • Add Column
  • Add Row
  • Remove Last Column
  • Remove Last Row
  • Edit Rows and Columns

The first 4 items are self explicit. The last item (Edit Rows and Columns) deserve that we spend more time. Selecting this item shows the dialog shown in figure 2.

Figure 2: The Column and Row Styles editor

It is quite obvious that you can add and delete columns and rows from that dialog. You can switch between the rows and columns mode by using the combo at the top. The right part of this dialog lets you decide the size the columns or rows will use. For example, figure 2 is showing 2 columns, each column having 50% of the space. When the TableLayoutPanel is resized, the columns and rows are resized according to these settings. You can mix all types of sizing. For example, you can have a column that has a fix (absolute) width of 100 pixels. You can also have 2 more columns one using 30% of the space left and the other using 70%. The AutoSize value will size the column (or row) according to its content.

Now that we have a table with a layout, we are ready to add controls to it. For example, add a button to the first cell of the table and check the properties of the buttons. Can you find new properties? Check again. Have you seen the Cell, Column, ColumnSpan, Row, RowSpan properties before for a plain old button control? You now have them because your button is hosted into a TableLayoutPanel. If you placed your button into the first cell, Column and Row will both be set to 0 as it is the coordinates (0-based) of the control into table. You can change it using the properties or you can move the control to another cell directly into the designer. The Cell property is a combination of Column and Row (much like the Location and the Size properties). The 2 xxxSpan controls work exactly like their HTML counterpart. They let you span a control through multiple rows and/or columns.

The Windows Forms version as a very serious limitation compared to its HTML equivalent. A single cell can contain only one control. As a workaround to this limitation, you can place another container control into a cell (like a Panel or a GroupBox) and then add multiple controls to this container control.

You could also use the Anchor or the Dock properties of the button so that it automatically resizes it whenever the TableLayoutPanel gets resized. If you need more granularities in your positioning, you can even place another TableLayoutPanel into a cell.

One thing I would like about this control is if it could be used as a splitter control.


I haven’t shown it here but both controls let you dynamically add contained controls at runtime by using the Controls.Add method of both the FlowLayoutPanel and the TableLayoutPanel controls.

Those controls are simply too easy to use to ignore them. They can be useful when the situation is right. Open the project you are currently working on and I am sure you will find a place or 2 where it perfectly fits.

I hope you appreciated the topic and see you next month.

(Print this page)