WPF Bootcamp

Layout Deep Dive

Most WPF bugs are layout bugs wearing another costume. If you understand how measure and arrange work, controls stop feeling random and panels become predictable tools.

WPF layout is recursive: parents ask children how much they want, then assign the final size they actually get. Once that clicks, "why is this stretching, clipping, or collapsing?" stops feeling mysterious.

What you'll learn

  • How measure and arrange differ.
  • Why panel choice controls nearly all sizing behavior.
  • How alignment, margins, width, height, and star sizing cooperate.
  • How to read layout bugs as a flow of size information through the tree.

The layout cycle

  1. Measure: parent gives available size, child returns desired size.
  2. Arrange: parent decides final slot and child lays itself out inside it.
  3. Render: the arranged result gets drawn.
<Grid Margin="24">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <TextBlock Grid.Row="0" Text="Header" FontSize="28" />
    <ListBox Grid.Row="1" Margin="0,16,0,16" />
    <Button Grid.Row="2" Content="Continue" HorizontalAlignment="Right" />
</Grid>

That grid is not merely stacking controls in order. It is negotiating space with each child, dividing the available height across rows, and then arranging each element into the slot it decided on.

The mental model in one sentence

Layout in WPF is a conversation between parent and child: the parent offers constraints, the child reports what it would like, and the parent still gets the final say.

Measure answers "How big do you want to be?"

The child receives available space and computes its desired size based on its content, explicit sizing properties, and its own internal rules.

Arrange answers "Here is the slot you actually get"

The parent decides the final rectangle for each child. Alignment and stretching then determine how the child uses that slot.

Why parent panels matter so much

Most layout behavior is not controlled by the child. It is controlled by the parent panel. The same Button will size and position differently depending on whether it lives in a Grid, StackPanel, DockPanel, or Canvas.

<Grid>
    <Button Content="Save" />
</Grid>

<StackPanel>
    <Button Content="Save" />
</StackPanel>

Those two buttons can behave differently even with identical button properties, because the parent panel's measure and arrange rules are different.

Practical takeaway: when a control looks wrong, inspect its parent panel before you start blaming the control itself.

Available size, desired size, and final size

These three ideas explain most layout outcomes.

  • Available size: what the parent offers during measure.
  • Desired size: what the child asks for after measuring its content.
  • Final size: what the parent ultimately assigns during arrange.

A child can desire more than it finally gets. It can also receive more space than it asked for and then stretch, center, or otherwise align itself inside that larger slot.

<Grid Width="400">
    <Button Content="Short" HorizontalAlignment="Center" />
</Grid>

The button may only need a small desired width for its text, but the grid can still arrange it inside a much wider slot. Alignment determines where it sits inside that slot.

Measure in practice

During measure, the parent panel asks each child: "Given this much room, how large would you like to be?" The child considers content, font metrics, padding, template visuals, min/max constraints, and explicit width/height settings.

<TextBlock
    Text="This title determines my desired size"
    FontSize="28" />

A bigger font produces a larger desired size. A longer string can change desired width or height. A text-wrapping setting changes the answer again. Measure is where content starts affecting geometry.

Panels may measure children with generous or restrictive constraints depending on their rules. That is why controls often report different desired sizes under different parents.

Arrange in practice

During arrange, the parent decides the actual rectangle each child gets. This is where the parent enforces structure: rows, columns, stacking order, docking rules, or absolute coordinates.

<Grid Width="500" Height="200">
    <Button
        Content="Continue"
        Width="140"
        HorizontalAlignment="Right"
        VerticalAlignment="Center" />
</Grid>

The grid owns the 500 by 200 area. The button does not negotiate that away. Instead, the grid arranges the button into a slot, and the button uses alignment and explicit width to position itself within it.

Panel behavior is the real layout API

Grid

Grid is the default panel for structured screens. It is powerful because it can combine fixed sizes, automatic sizing, and proportional sizing.

  • Auto means size to content.
  • A fixed number means exactly that size.
  • * means take a proportional share of the remaining space.
<Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>

After satisfying fixed and auto columns, the remaining width is split proportionally between the star columns.

StackPanel

StackPanel is simple and useful, but it is not a universal default. It stacks children in one axis and can give them effectively unconstrained size in that stacking direction, which sometimes leads to surprising measurement results.

DockPanel

DockPanel is great for shell layouts like top bars, sidebars, and fill-content structures. Children dock one by one, and the remaining space goes to the last child by default.

Canvas

Canvas uses explicit coordinates. That makes it useful for overlays and special cases, but it opts out of most of the adaptive behavior that makes WPF layout powerful.

Alignment, margin, padding, width, and height

These properties cooperate, but they do different jobs.

  • Margin adds space outside an element.
  • Padding adds space inside a control around its content.
  • Width and Height set explicit size requests or constraints.
  • HorizontalAlignment and VerticalAlignment decide how an element uses the slot it receives.
<Button
    Content="Save"
    Margin="12"
    Padding="16,8"
    HorizontalAlignment="Right" />

That button gets external spacing from margin, internal spacing from padding, and right positioning from alignment. These are not interchangeable knobs.

A common confusion is expecting alignment to change the amount of space the parent allocated. It does not. Alignment only affects how the element sits inside the slot it already received.

Stretching and why it sometimes seems to stop working

Stretch alignment only matters when the parent offers extra space and the panel type allows that extra space to exist meaningfully. Some parents constrain or measure children in ways that make stretch appear ineffective.

<StackPanel>
    <TextBox HorizontalAlignment="Stretch" />
</StackPanel>

New WPF developers often expect that text box to stretch exactly the way it would inside a grid. Sometimes it will not behave as expected because StackPanel measurement rules differ from Grid rules. This is not the text box being inconsistent. It is the panel changing the layout conversation.

Scrolling changes the layout conversation

A ScrollViewer changes available size semantics because it may allow content to exceed the viewport. That can affect how descendants measure themselves, especially in the scrollable direction.

<ScrollViewer VerticalScrollBarVisibility="Auto">
    <StackPanel>
        <TextBlock Text="A lot of content..." />
    </StackPanel>
</ScrollViewer>

When scrolling is involved, a child may measure differently because the viewport and the scrollable extent are not the same thing. This is one reason nested scrolling or deeply nested stack panels can become confusing quickly.

Common panel choices and when to use them

Use Grid for most screens

It handles forms, dashboards, master-detail layouts, and shells because it supports explicit structure without giving up flexibility.

Use StackPanel for simple flows

It is good for short tool groups, small forms, or linear sections, but it is easy to overuse.

Use DockPanel for frame layouts

It maps naturally to headers, side rails, status bars, and a final fill area.

Use Canvas sparingly

Choose it when you truly want coordinates, not when you just want to "make things go where I want".

A worked example

Read this screen as a size negotiation:

<Grid Margin="24">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <TextBlock
        Grid.Row="0"
        Text="Orders"
        FontSize="28" />

    <ListBox
        Grid.Row="1"
        Margin="0,16,0,16" />

    <Button
        Grid.Row="2"
        Content="Continue"
        Width="140"
        HorizontalAlignment="Right" />
</Grid>
  1. The grid receives available space from its parent, reduced by its outer margin.
  2. The first row measures to the text block's desired height because it is Auto.
  3. The last row measures to the button's desired height because it is also Auto.
  4. The middle row gets the remaining height because it is *.
  5. The list box is arranged into that remaining area, minus its own margins.
  6. The button gets a slot across the bottom row, but its explicit width and right alignment determine how it sits inside that slot.

That step-by-step reading is how experienced WPF developers debug layout. They track size decisions instead of guessing visually.

Common mistakes

  • Using nested StackPanel everywhere and then wondering why stretching or scrolling behaves poorly.
  • Forgetting that Auto, fixed values, and * mean very different things in a Grid.
  • Setting both explicit size and aggressive margin/alignment values without understanding which one is fighting the layout result.
  • Debugging a child control in isolation when the parent panel is actually deciding the behavior.
  • Using Canvas to escape the layout system instead of learning the layout system.

InkkSlinger parity note: The same parent-measures-child model applies here. If an InkkSlinger view looks wrong, the first thing to inspect is usually the panel tree and the size information flowing through it.

Next, learn how controls relate to content, because layout explains where things go, but the content model explains what kinds of things a control can host in the first place.