Table of Contents

Layout

This topic describes the AlterNET UI layout system. Understanding how and when layout calculations occur is essential for creating user interfaces in AlterNET UI.

Control Bounding Boxes

When thinking about layout in AlterNET UI, it is important to understand the bounding box that surrounds all controls. Each Control consumed by the layout system can be thought of as a rectangle that is slotted into the layout. The size of the rectangle is determined by calculating the available screen space, the size of any constraints, layout-specific properties (such as margin and padding), and the individual behavior of the parent control. By processing this data, the layout system can calculate the position of all the children of a particular Control. It is important to remember that sizing characteristics, defined on the parent control, such as a Border, affect its children.

The following illustration shows a simple layout.

Screenshot that shows a typical grid, no bounding box
superimposed.

This layout can be achieved by using the following UIXML.

<Grid Name="myGrid" Height="150">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="250"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Border Name="border1" Grid.Column="0" Grid.Row="0" BorderBrush="{x:Null}">
        <Label Margin="5" Text="Hello World!" />
    </Border>
    <Button Width="125" Height="25" Grid.Column="0" Grid.Row="1" Text="Show Bounding Box" Click="ShowBoundingBoxButton_Click" />
    <Label Name="txt2" Grid.Column="1" Grid.Row="2"/>
</Grid>

A Label control is hosted within a Grid. While the text fills only the upper-left corner of the first column, the allocated space for the containing Border is actually much larger. The bounding box of any Control can be retrieved by using the Bounds method. The following illustration shows the bounding box for the Label control.

Screenshot that shows that the Border bounding box is now
visible.

As shown by the orange rectangle, the allocated space for the Label control is actually much larger than it appears. As additional controls are added to the Grid, this allocation could shrink or expand, depending on the type and size of controls that are added.

The layout bounds of the Border are highlighted by setting the BorderColor property.

private void ShowBoundingBoxButton_Click(object? sender, EventArgs e)
{
    border1.BorderBrush = Brushes.Orange;
    txt2.Text = border1.Bounds.ToString();
}

The Layout System

At its simplest, the layout is a recursive system that leads to control being sized, positioned, and drawn. More specifically, layout describes the process of measuring and arranging the members of a Control's Children collection. The layout is an intensive process. The larger the Children collection, the greater the number of calculations that must be made. Complexity can also be introduced based on the layout behavior defined by the Control control that owns the collection. A relatively simple layout Control, such as Border, can have significantly better performance than a more complex Control, such as Grid.

Each time that a child Control changes its position, it has the potential to trigger a new pass by the layout system. Therefore, it is important to understand the events that can invoke the layout system, as unnecessary invocation can lead to poor application performance. The following describes the process that occurs when the layout system is invoked.

  1. A child Control generally begins the layout process by first measuring itself by having its core sizing properties evaluated, such as Width, SuggestedWidth, SuggestedHeight, Height, and Margin.

  2. After that, a custom GetPreferredSize implementation may change the desired control's size.

  3. Layout using Dock property.

  4. Layout Control-specific logic is applied, such as StackPanel's OnLayout logic and its related properties, such as Orientation.

  5. The control bounds are set after all children have been measured and laid out.

  6. The process is invoked again if additional Children are added to the collection, or the PerformLayout method is called.

Measuring and Positioning Children

The layout system typically performs two operations for each member of the Children collection, a measure and a layout. Each child Control provides its own GetPreferredSize and OnLayout methods to achieve its own specific layout behavior.

By default, a control provides a base measure and layout logic. It considers several base control inputs to perform its operation.

First, native size properties of the Control are evaluated, such as Visible. Secondly, the properties which affect the value of the control's preferred size are processed. These properties generally describe the sizing characteristics of the underlying Control, such as its Height, Width, Margin, Padding, Layout, Dock, HorizontalAlignment, and VerticalAlignment. Each of these properties can change the space that is necessary to display the control.

The ultimate goal of the measurement process is for the child to determine its preferred size, which occurs during the GetPreferredSize call.

During the layout process, the parent Control control generates a rectangle that represents the bounds of the child. This value is set to the Bounds property.

The layout logic evaluates the preferred size of the child and evaluates any additional properties that may affect the actual size of the control, such as margin and alignment, and puts the child within its layout slot. The child does not have to (and frequently does not) fill the entire allocated space. After that, the layout process is complete.

Standard Layout Controls

AlterNET UI includes a group of controls that enable complex layouts. For example, stacking controls can easily be achieved by using the StackPanel control, while more complex layouts are possible by using a Grid.

The following table summarizes the available layout controls.

Control name Description
Grid Defines a flexible grid area that consists of columns and rows.
StackPanel Arranges child controls into a single line that can be oriented horizontally or vertically.
VerticalStackPanel Arranges child controls into a single line that can be oriented vertically.
HorizontalStackPanel Arranges child controls into a single line that can be oriented horizontally.
SplittedPanel Manages subcontrols which are aligned to the sides with splitter control between them.
LayoutPanel Arranges child controls using different methods.
Splitter Provides resizing of docked controls.

Custom Layout Behaviors

For applications that require a layout that is not possible by using any of the predefined controls, custom layout behaviors can be achieved using one of these approaches: