1. Introduction To C# TableLayoutPanel Container
Do you know how the Table works in html? The “TableLayoutPanel” works almost the same way how the table works in html. In this example, we will see how the C# TableLayoutPanel can be used & how each cell of this panel behaves. Also, we will nest some other layout panel with this one. At the end we will see a small professional looking form that can be used by any hospital management application.
OK. The C# TableLayoutPanel is collection cells and these cells can be arranged in rows and columns. We can imagine each cell as a special container. Why we say that it is a special container? Because each cell can hold only one control in it. What if we need to have multiple controls in one cell? Actually, that is not required most of the time for this container. But if we still need an answer, place a container you like in that cell and start placing the controls inside the container which occupying the cell. Say, for example, we can place a Panel in a cell and add multiple controls to that Panel.
2. About This Example
Look at the screen shot given of the C# TableLayoutPanel Example below:

C# TableLayoutPanel Example
The Form shows a Hospital Bed allocation system. Top of the form shows three floors and beds are arranged in two rows on each floor. Each row in each floor has space for 15 beds. A scroll bar is provided to see all the beds as the screen initially displays 10 beds on each floor completely. When we click a ‘Bed Number’ the bed goes to the allocated mode, and that is shown in yellow color with a check mark in it. To reserve a bed, we have to select the floor number in the combo box. The North entries in the combo box denotes first row in the floor and South denotes second row. After this, we can specify the Bed number to lock it as reserved.
Why reservation flow is complex?
One may think why such a complex workflow to reserve a bed and it can be done with a right click. But we had taken this to study the functions exposed by this container and also to explore the nested containers. To have more nice appearance, one can place a legend at the bottom of the panel that says Yellow: Allotted. Red: Reserved. Dark Blue: Available.
Now we will begin to implement this example. This article has embedded YouTube videos to avoid lots of screenshots. One can watch the videos in full-screen mode. In the future, the site will upload Hi-Res videos.
3. Arranging C# TableLayoutPanel & Splitter
First, we create a C# Windows Form Application and after that we add a Split Container Control in the main form. Then the container’s splitter is put horizontally. At this stage the Panel1 is on the top and Panel2 is in the bottom. Once the Splitter is ready, we place the C# TableLayoutPanel inside the Panel1 of the split container. Now we have the nested containers. The Form is the container which gives room for the Splitter treating it as a control. Splitter acts as a container and gives room to take in the TableLayoutPanel Container. And this Table Layout container will have many controls in it. This is shown in the below video:
Finally, we set Fill Dock style to our TableLayoutPanel. This makes the TableLayoutPanel to take up the full area of the Panel1 of the Split Container Control.
4. Manage Containers Via Document Outline View
As we have nested containers, it will be hard to select a specific container. Now it is time to know what is the usage of the “Document Outline Window”. This view comes in handy to know the parent-child relationship between the container.
The Document Outline Window not only shows the relation between the containers, it also helps us to pick the exact one we want. Using this Document Outline window, we can easily pick and rename the splitter of the Split container and TableLayoutPanel. The below picture shows the Document Outline window:

Document Outline View
The above picture shows the Document Outline view. It shows the container outline of our form. We can access it from the view menu. The outline shows that Form is the topmost container, and it holds the Split container. C# TableLayoutPanel is contained inside the Panel1 of the Split container. Panel2 of split container does not have any control in it.
The below video (No Audio) shows how we rename the SplitConianer and TableLayoutPanel:
5. Adding Rows to C# TableLayoutPanel Container
In this step, we add all six rows required for the TableLayoutPanel. First, we select it using the Document outline view. Then, we add six rows using the ‘Edit Rows and Columns’ option of Quick Menu item. For all the six rows, we set the size property as AutoSize and it will resize each cell based on the control it contains. Other size mode is self-explanatory, and one can play around it to know how they work.
For ease we set only one column for our TableLayoutPanel. By default, Visual Studio adds two columns to the TableLayoutPanel control, and we cut out one column to have only six rows in the control. The below video (No Audio) shows how we add rows to our container:
6. Place Controls on Panel2
In the bottom Panel of the Split container, we place all other supporting controls including the label which gives confirmation message when a bed allotted. To place the controls, we can drag the control from the toolbox and drop it in the bottom panel of the SplitContainer control. The below video shows how we place supporting controls in Panel2:
Note that later we must add a label and Button to reserve the beds. Refer the screenshot in section 2 or download the example to know the list of controls in panel2. Use Document outline view in the downloaded application.
7. AutoScroll Property of TableLayoutPanel
We set AutoScroll property for the Panel1 of the Split Container as well as for the C# TableLayoutPanel, which is inside the Panel1. Setting auto scroll for the Panel1 is not that much important for this example. But Autoscroll for the table is important as it will accommodate 15 check boxes in a row. So what is the need of the Auto Scroll for Panel1? For our example, we do not need it at all. But, if we want to add more controls outside of the TableLayoutPanel and inside the Panel1 of SplitContainer, it will be useful. The video shows setting auto scroll for the Panel1. One can follow the same steps for TableLayoutPanel control as well. This is shown in the video:
8. Placing Floor Labels
Our example needs three labels to display the floor number. Before placing the labels, we set the ‘
CellBorderStyle
Property’ of the C# TableLayoutPanel control to ‘
Inset
’. Once we set, the top portion of the TableLayoutPanel is shown as some multiple lines. This is because we set the
SizeType
as
autosize
in Section 5 of this article. After doing this, we have to place the Label inside the open cell of the Table Layout. Then adjust the Row property. The below video shows adding a floor in row 0. One can repeat this step for other two labels as well.
9. RowSpan of the TableLayoutPanel
As we know, the C# TableLayoutPanel contains rows and columns. These rows and columns together form a Cell. Each Cell in the Layout can hold only one control or container. Now we have six rows and one column. But we want to place a label for each two rows of beds. We want to have six rows of beds and two rows belongs to one label. The idea here is, the Labels represents three floors, and each floor is having two rows of beds.
The way we can achieve this is through the Row Span in this case. If we want to combine more column for one control, we can use Column Span. We can also use ‘
RowSpan
’ and ‘
ColumnSpan
’ together. These spans will say how many rows or columns a control want to extend. In our case, each label in the only existing column want to extend two rows. So we set
Rowspan
for these labels to 2. The finished form is shown below.

Floor Labels Set with RowSpan as 2
The below video shows setting RowSpan to 2 for One label (Floor 3). One can do the same for other two labels:
Once everything is done, we set all the rows to use 15% of the Panel1’s width. This will be helpful when the user resizes the panel. At present we fixed this panel using the “
IsSplitterFixed
Property”. The below video shows how to set this:
10. GrowStyle Property of TableLayoutPanel
Now we will add the Beds (Checkboxes) using the C# code. The ‘
GrowStyle
Property’ that we do not talk about till now is useful to say how the cells added to the Table layout. We can fix the number of cells by using the ‘
RowCount
’ and ‘
ColumnCount
’ property of the control. Once cells are fixed and Layout is full of the control, the GrowStyle property tells how layout should accommodate the new incoming control.
This property accepts three values from the
TableLayoutPanelGrowStyle
enumeration. The table below shows the how panel behaves for each constant value:
Property Constant | Description |
---|---|
AddColumns | The TableLayoutPanel adds a new column to house the incoming control. |
AddRows | The TableLayoutPanel adds a new row to house the incoming control. |
FixedSize | The TableLayourPanel does not add a row or column. It does not allow additional controls when the grid is filled. |
From the table, if we set the
FixedSize
enumeration constant to GrowStyle property, we can’t add new controls to TableLayoutPanel Control after it got filled..
Addrows
and
AddColumns
value of the property allows new controls by adding a fresh row or column depending on the property value.
In our example, we will add control by specifying the exact location and because of that we set
GrowStyle
as fixed. All set & we will start our coding. First, we need to create all the check boxes while form loads and hook those to the event handler on the fly. Then we will implement the event handler.
11. Form Load Event Handler
In the form load event handler, we are creating all the beds for each floor and linking that with the event handler. The event hooked to the handler is
checkstatechanged
.
11.1 Setting GrowStyle
First, we are setting the
GrowStyle
property of the TableLayoutPanel to
FixedSize
. Then we are setting the column count to 16. Note that we will place only 15 beds in a row. Also, remember that we already used one column to specify the floor names. After the executing the below code, our TableLayoutPanel will have 16 Columns and 6 Rows.
1 2 3 |
//TableLayout 001: First Set the Properties for the Table Layout contTable.GrowStyle = TableLayoutPanelGrowStyle.FixedSize; contTable.ColumnCount = 16; |
11.2 Nested Loop to Fill TableLayoutPanel
Next, we create a nested ‘for loop’. The outer one iterates through each floor, and an inner one iterates through each bed. The for loop is given below:
1 2 3 4 5 6 7 |
//TableLayout 002: Add check boxes to the Panel for (int row = 0; row < 6; row++) { for (int col = 1; col < 16; col++) { } } |
11.3 Setup the Check Boxes
Inside the For loop we are creating the check boxes (Bed Slot) and setting its dock style to
Fill
. This will ensure that the checkbox is fully occupied inside the cell of the C# TableLayoutPanel container.
1 2 3 4 5 |
//002.1 : Create Checkbox CheckBox chkbx = new CheckBox(); chkbx.Text = col.ToString(); chkbx.Dock = DockStyle.Fill; chkbx.AutoSize = true; |
11.4 Handler Function For Check Boxes & Filling the Grid Of TableLayoutPanel
Now we will hook the
CheckStateChanged
event with the handler function
AlotOrFreeBed
. We do this with a
+=
operator. Note that dot net expects specific types of parameters in the event handler function. Our handler function
AlotOrFreeBed
agrees to that rule. That’s all! The check boxes are ready and we add it to the TableLayoutPanel container using
add
method of the
Controls
collection. Note that when we are adding we specify the cell location. In our case we specified the location using
col
and
row
local variables.
1 2 3 4 5 |
//002.2 : Hook the Checkbox event chkbx.CheckStateChanged += new System.EventHandler(AlotOrFreeBed); //002.2 : Add to the TableLayoutPanel contTable.Controls.Add(chkbx, col, row); |
12. AlotOrFreeBed Handler Function For All Check Boxes
All our check boxes are now laid out in the TableLayoutPanel Container. They fire CheckStateChanged event when user clicks on it. Note, when user places a check mark on a check box in the grid, we should show that user allotted the bed. We can show that visually by changing the color of the Check box to yellow along with a check mark in it.
12.1 Finding The Event Source
Note, in the past section (11.4) we linked the
CheckStateChange
event of all the check boxes to the function
AlotOrFreeBed
. So we should know which check box is firing the event. C# will send that in a parameter called sender. We can type cast that as a
Control
so that we can esquire its position from the TableLayoutPanel by calling the
GetPositionFromControl
function. This function returns
TableLayoutPanelCellPosition
. It is a structure representing control’s position as row & column. In the below code, we store this structure in a variable called position.
1 2 3 4 |
//003.1 : Get the Row Position of the Checkbox first Control C = (Control) sender; int FloorNumber; TableLayoutPanelCellPosition position = contTable.GetPositionFromControl(C); |
12.2 Get Floor Location
We decide the floor number based on the row value taken from the position returned by the previous code snippet and we assign the floor number to a local variable called
FloorNumber
. Now we know which bed a user is allotting, and in which floor it resides.
1 2 3 4 5 6 7 |
//003.2 : Get the Floor Number if (position.Row > 1 && position.Row < 4 ) FloorNumber = 2; else if (position.Row < 2) FloorNumber = 3; else FloorNumber = 1; |
12.3 Bed State – Allotted or Free?
We are using the one more reference for same sender. This time we are type-casting it as Checkbox. This reference is useful for checking the Checked State of the check box. When the check box is in the checked state, we form a message that says bed is allocated otherwise it says bed is Freed. Also, we set different background and foreground color to differentiate the allocated beds the free beds in grid if beds. Below is the code for it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//003.3 : Frame the information display string CheckBox chk = (CheckBox)sender; if (chk.Checked == true) { chk.BackColor = Color.Yellow; chk.ForeColor = Color.Black; lblDisplay.Text = string.Format("Bed Number {0} allocated on Floor {1}", chk.Text, FloorNumber); } else { chk.BackColor = this.BackColor; chk.ForeColor = this.ForeColor; lblDisplay.Text = string.Format("Bed Number {0} Freed on Floor {1}", chk.Text, FloorNumber); } |
13. Reserve Button Click Handler
The event routine is almost same to the previous. There is nothing much to specify here except that we are directly getting the control from the C# TableLayoutPanel by telling the cell position in terms of row and column. The function
GetControlFromPosition
is just a reverse of what we used in the previous event handler. Below is the code that disables the reserved bed, and we set background to Red. Once the bed is in reserved user can not assign it. Note, we can easily reserve the bed with a right click. But here we learnt how to get the control from TableLayoutPanel from its position.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//TableLayout 004: Reserve the Bed private void btnReserve_Click(object sender, EventArgs e) { //004.1 : Get the Cell Row and Cell Column from user selection. (5-x) is to get the High Floor for low index int Row = 5 - cboFloor.SelectedIndex ; int Col = cboBedNo.SelectedIndex + 1; //004.2 : Now get the Control from the Cell Position Control C = contTable.GetControlFromPosition(Col, Row); C.BackColor = Color.Red; C.ForeColor = Color.Black; C.Enabled = false; } |
Download from Google Drive: C# TableLayoutPanel Example
Note: This Example was created using VS2005 IDE. One can convert it to any latest version of Visual Studio.
Categories: C#
Tags: AutoScroll, C# Container Controls, C# GetPositionFromControl, GetControlFromPosition, GrowStyle, RowSpan & ColumnSpan, TableLayoutPanelCellPosition