Quick Tip: Dynamically Add Rows, Columns and Controls to Delphi’s TGridPanel

Delphi’s TGridPanel control is an ideal pick when you want to create grid-flow like user interface layout for your controls.

To place controls on a grid panel you specify the number of rows and columns (RowCollection and ColumnCollection properties) and simply drop a control on it. Unlike standard TPanel, when you drop a control on a GridPanel it will be placed in the next available empty cell in the grid. As you add more controls the grid will grow either by rows or columns being added automagically (or not, if the ExpandStyle poroperty is set to emFixedSize). What’s more you can even determine how each cell will be sized: will it have a fixed size, or a percentage of the grid size – so you can have controls nicely uniformly distributed in a grid.

That’s all great when you know the design at design-time – and you know what number of controls you want to be hosted by the grid panel.

What if you need to dynamically add controls to grid panel at run-time?

Say you do not know the number of rows or columns at design time, but you need to add controls to the grid panel dynamically where the number of rows/columns (/controls) changes. You’ll have to deal with RowCollection and ColumnCollection properties (to add or remove rows/columns). You’ll have to specify the SizeStyle for each cell and finally you have to somehow add a control to each cell.

So, without further ado, here’s how to add controls to GridPanel dynamically:

procedure TForm1.FormCreate(Sender: TObject);
  GridPanel1.Caption := '';


procedure TForm1.CreateButtonGrid(const rowCount, colCount : integer);
  i : integer;
  aButton: TButton;

  for i := 0 to -1 + GridPanel1.ControlCount do

  //btw, cannot clear if there are controls, so first remove "old" controls above

  for i := 1 to rowCount do
    with GridPanel1.RowCollection.Add do
      SizeStyle := ssPercent;
      Value := 100 / rowCount; //have cells evenly distributed

  for i := 1 to colCount do
    with GridPanel1.ColumnCollection.Add do
      SizeStyle := ssPercent;
      Value := 100 / colCount; //have cells evenly distributed

  for i := 0 to -1 + rowCount * colCount do
    aButton := TButton.Create(self);
    aButton.Parent := GridPanel1; //magic: place in the next empty cell
    aButton.Visible := true;
    aButton.Caption := 'Btn ' + IntToStr(i);
    aButton.Align := alClient;
    aButton.AlignWithMargins := true;


So, on the form I have a GridPanel1 and the CreateButtonGrid(3,5) procedure will place 12 buttons in a 3 rows x 4 columns grid, each cell of the same size, buttons filling the cell with a pinch of margin. As you resize the form, buttons grow or shrink but are still evenly distributed in 3×4 grid. Nice!

And two extras:

Get Control at Row/Column

To get the control placed in a specified row / column you can use:

  aControl : TControl;
  aControl := GridPanel1.ControlCollection.Controls[2,3]; //3rd row, 4th column
  if Assigned(aControl) AND (aControl IS TButton) then
    TButton(aControl).Caption := 'No hiding in 2,3';

Get Row and Column where Control is

Now, you know a control is somewhere in the grid panel, and you need to know in what row / column:

  aControl : TControl;
  idx : integer;
  cRow, cColumn : integer;
  //"pseudo" code (as aControl is nil)

  cRow := -1; cColumn := -1;
  idx := GridPanel1.ControlCollection.IndexOf(aControl);
  if idx > -1 then
    cRow := GridPanel1.ControlCollection[idx].Row;
    cColumn := GridPanel1.ControlCollection[idx].Column;

Yes, the TGridPanel can be tricky to use, but when you find a use for it – you will not know how you lived without it 🙂

7 thoughts on “Quick Tip: Dynamically Add Rows, Columns and Controls to Delphi’s TGridPanel

  1. Ali Dehban

    I found the ‘Gridpanel’ very useful.
    Actually the best practice is not ‘ssPercent’ Size Style, and ‘ssabsolute’ style let you optionally and manually determine row/col size and its working very well at run time with a lot of controls on form.

  2. Nuzzi

    Yeah, ssPercent is a bit odd. If you set it during run time I have had to put it into a while loop until the value is what you want. Maybe there is a better way, but I have not discovered it.

  3. Erik Langendoen

    There is no rowcount or colcount property. When changed that to rowCollection.Count the code still does not work. It looks like TGridPanel is broken in Delphi 10.4

  4. Christian Lindenblatt

    I think in Get Control at Row/Column chapter row an col is reversed. It is the 3rd col and the 4th row.


Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.