Click here to Skip to main content
Click here to Skip to main content

WPF Layouts - A Visual Quick Start

By , 5 Mar 2009
 

WPF Visual Quick Start Articles by Josh Fischer

Introduction

Switching from WinForms UI development to WPF can be intimidating. The question I kept asking myself is, "Where do I start?" Hopefully, this article will help you quickly develop a good starting point for WPF as it did for me. The examples are written in XAML, as it can be easily copied and pasted into the Visual Studio (or any other) designer. My goal is to show how the layouts work with screenshots and XAML, instead of using text descriptions.

Background

Layouts are the mechanism that WPF uses to define how visual items will be displayed on the screen for standard 2D applications. This concept is not new, and if you have used any of the Panel controls in WinForms (FlowLayoutPanel, TableLayoutPanel, etc.), you will not have any trouble understanding the basic layouts in WPF. In their simplest form, the layout classes are nothing more than containers for the other controls in your application and handle the positioning of those controls for you.

The Layouts

  • StackPanel - Arranges controls in a line, either horizontally or vertically.

    <StackPanel Orientation="Vertical"> <!-- Vertical is the default -->
      <Label Background="Red">Red 1</Label>
      <Label Background="LightGreen">Green 1</Label>
      <StackPanel Orientation="Horizontal">
        <Label Background="Red">Red 2</Label>
        <Label Background="LightGreen">Green 2</Label>
        <Label Background="LightBlue">Blue 2</Label>
        <Label Background="Yellow">Yellow 2</Label>
        <Label Background="Orange">Orange 2</Label>
      </StackPanel>
      <Label Background="LightBlue">Blue 1</Label>
      <Label Background="Yellow">Yellow 1</Label>
      <Label Background="Orange">Orange 1</Label>
    </StackPanel>
    Note:
    • Items are stretched to fit their contents (text) and to fit the window.
    • By default, items will not fill all the available space (whitespace in screenshot).
    • Layouts can be nested within one another.
  • WrapPanel - Arranges items in a line until the border is hit, then wraps to the next line.

    Vertical orientation

    Horizontal orientation
    <WrapPanel Orientation="Vertical">
      <Label Height="125" Background="Red">Red 1</Label>
      <Label Height="100" Background="LightGreen">Green 1</Label>
      <Label Height="125" Background="LightBlue">Blue 1</Label>
      <Label Height="50" Background="Yellow">Yellow 1</Label>
      <Label Height="150" Background="Orange">Orange 1</Label>
      <Label Height="100" Background="Red">Red 2</Label>
      <Label Height="150" Background="LightGreen">Green 2</Label>
      <Label Height="75" Background="LightBlue">Blue 2</Label>
      <Label Height="50" Background="Yellow">Yellow 2</Label>
      <Label Height="175" Background="Orange">Orange 2</Label>
    </WrapPanel>
    
    <WrapPanel Orientation="Horizontal"> <!-- Horizontal is the default -->
      <Label Width="125" Background="Red">Red 1</Label>
      <Label Width="100" Background="LightGreen">Green 1</Label>
      <Label Width="125" Background="LightBlue">Blue 1</Label>
      <Label Width="50" Background="Yellow">Yellow 1</Label>
      <Label Width="150" Background="Orange">Orange 1</Label>
      <Label Width="100" Background="Red">Red 2</Label>
      <Label Width="150" Background="LightGreen">Green 2</Label>
      <Label Width="75" Background="LightBlue">Blue 2</Label>
      <Label Width="50" Background="Yellow">Yellow 2</Label>
      <Label Width="175" Background="Orange">Orange 2</Label>
    </WrapPanel>
    Note:
    • Items are stretched to fit their contents (text).
    • If an item cannot fit entirely in the allotted space, the entire control is moved to the next line.
  • DockPanel - Places controls in five different regions: top, bottom, left, right, or center (fill).

    <DockPanel>
      <Label DockPanel.Dock="Top" Height="100" Background="Red">Red 1</Label>
      <Label DockPanel.Dock="Left" Background="LightGreen">Green 1</Label>
      <Label DockPanel.Dock="Right" Background="LightBlue">Blue 1</Label>
      <Label DockPanel.Dock="Bottom" Background="LightBlue">Blue 2</Label>
      <Label DockPanel.Dock="Bottom" Height="50" Background="Yellow">Yellow 1</Label>
      <Label Width="100" Background="Orange">
    			Orange 1</Label>   <!-- default is to fill -->
      <Label Background="LightGreen">Green 2</Label>
    </DockPanel>
    Note:
    • Child elements tell the parent DockPanel where they should be placed (DockPanel.Dock="Top").
    • You can place more than one control in a region (Yellow 1 and Blue 2).
    • If you do not specify a region, then the item will be set to fill (default behavior).
    • Items are stretched to fit their contents (text) and to fit the region they are in.
    • The size of any non-fill region is dictated by its contents (Red 1 has a height specified so it is larger).
  • Canvas - Explicitly position controls based on coordinates.

    <Canvas>
      <!-- default coordinates 0,0 from top left; like WinForms -->
      <Label Background="Red">Red 1</Label>
      <Label Canvas.Right="50" Background="LightGreen" >Green 1</Label>
      <Label Canvas.Top="100" Canvas.Left="100" Background="LightBlue" >Blue 1</Label>
      <Label Canvas.Bottom="166" Canvas.Right="237" Background="LightBlue" >
    						Blue 2</Label>
      <Label Canvas.Right="300" Canvas.Top="250" Background="Yellow" >Yellow 1</Label>
      <Label Canvas.Right="50" Canvas.Bottom="50" Background="Orange" >Orange 1</Label>
    </Canvas>
    Note:
    • Child elements tell the parent Canvas where they should be placed (Canvas.Right="50").
    • When no dimensions are specified, the labels are stretched to fit their contents (text).
    • Controls can be placed relative to any side of the window (Blue 1 vs. Blue 2).
    • Top overrides Bottom and Left overrides Right.
  • UniformGrid - Maintains a series of grid cells of equal size.

    <UniformGrid>
      <Label Background="Red">Red 1</Label>
      <Label Background="LightGreen">Green 1</Label>
      <Label Background="LightBlue">Blue 1</Label>
      <Label Background="Yellow">Yellow 1</Label>
      <Label Background="Orange">Orange 1</Label>
      <Label Background="Red">Red 2</Label>
      <Label Background="LightGreen">Green 2</Label>
      <Label Background="Yellow">Yellow 2</Label>
      <Label Background="Orange">Orange 2</Label>
    </UniformGrid>
    Note:
    • Items are stretched to fit the cell.
    • The total number of cells increases by square integers.
      # items # cells square of
      1 1 1
      2-4 4 2
      5-9 9 3
      10-16 16 4
      17-25 25 5
      ... ... ...
  • Grid - Defines static columns and rows; like HTML tables.

    <!-- First screenshot -->
    <Grid>
      <!-- Using default column and row configurations -->
      <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
      </Grid.RowDefinitions>
    
      <Label Grid.Column="0" Grid.Row="0" Background="Red">Red 1</Label>
      <Label Grid.Column="1" Grid.Row="0" Background="LightGreen">Green 1</Label>
      <Label Grid.Column="0" Grid.Row="1" Background="LightBlue">Blue 1</Label>
      <Label Grid.Column="1" Grid.Row="1" Background="Yellow">Yellow 1</Label>
      <Label Grid.Column="0" Grid.Row="2" Background="Orange">Orange 1</Label>
    </Grid>
    
    <!-- 2nd screenshot uses ColumnSpan and RowSpan -->
    <Label Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" 
           Background="Red">Red 1</Label>
    <Label Grid.Column="0" Grid.Row="1" Grid.RowSpan="3" 
           Background="LightGreen">Green 1</Label>
    Note:
    • Child elements tell the parent grid what cell they should be in.
    • Items are stretched to fill the cell.
    • Each row or column can be given a specific size (Height/Width).
    • Cell contents can be told to span multiple rows (RowSpan) or columns (ColumnSpan).

Points of Interest

Please note this article is intended as a -visual- quick start for beginners. For a more in depth discussion, please see Sacha Barber's excellent article, or refer to the MSDN documentation.

History

  • 11/12/2008: Initial version
  • 11/21/2008: Fixed formatting errors made by CodeProject editors
  • 3/3/2009: Added related article index

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Josh Fischer
Software Developer (Senior)
United States United States
Member
CodeProject MVP 2010
CodeProject prize winner - Best C# article of December 2009


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionHow to "Anchor" [modified]memberCélio9 May '13 - 1:07 
Hi.
 
I am stuck on this because on Windows Forms we have anchors and if I want to center a control vertically i just remove top and bottom anchors and it centers itself vertically.
If I have 3 controls with this configuration and if I resize the form vertically the controls contracts ou retracts the space between them.
I am working with the Grid Control and want the Image controls to overlap with each other but slide between them (vertically centered) with the resize of the form.
 
I hope I was clear enough explaining my problem and that you can help me with this.
 
Thanks in advance.
CeliSoft


modified 9 May '13 - 7:16.

QuestionMy vote 5 [modified]memberNitin Sawant30 Oct '12 - 0:58 
Thanks,
From your article series I got starting point for WPF learning Big Grin | :-D
 
WPF Layouts are similar to Java Swing Sniff | :^)
 
1. I wonder how to implement animations in WPF windows desktop app?
e.g. App startup form transitions in windows 8 metro start menu
2. & how to get the horizonatal scrollbar like metro start menu?
 
Regards,
NJ
============================================
The grass is always greener on the other side of the fence


modified 30 Oct '12 - 7:12.

GeneralMy vote of 5memberMember 83548614 Nov '11 - 8:39 
Cuts to the point with examples that we can really use.
GeneralMy vote of 5memberDavidFine1320 Oct '10 - 3:54 
to the point
GeneralRe: My vote of 5mvpJosh Fischer26 Oct '10 - 6:15 
thanks for the vote
Josh Fischer

GeneralMy vote of 5memberMember 3940519 Sep '10 - 19:42 
cool
GeneralRe: My vote of 5mvpJosh Fischer27 Sep '10 - 4:06 
Thanks for the vote.
Josh Fischer

GeneralGood stuffmemberDmitri Nesteruk12 Nov '08 - 7:29 
This is precisely the kind of articles that beginner developers need – clear, concise and visual. Gets my 5.
GeneralRe: Good stuffmemberCarl Lambrecht17 Nov '08 - 8:28 
Even as an experienced .Net 2.0 developer migrating to .Net 3.5, I found this article to be a straight-forward visual reference to the various layouts now available in WPF. It's not rocket science, but it's a simple answer to a simple question. Much appreciated!
 
Cheers,
Carl
GeneralRe: Good stuffmvpJosh Fischer26 Jul '10 - 3:37 
I'm glad it helped you!
Josh Fischer

GeneralRe: Good stuffmvpJosh Fischer26 Jul '10 - 3:38 
Thanks...a year and a half later. Sorry, I guess I got stuck in a wormhole. Laugh | :laugh:
Josh Fischer

GeneralJust What I Needmembermark_w_12 Nov '08 - 5:19 
Thats a great simple artical.
 
I am about to start a new project and intend using wpf for the first time, so this will help me get started.
 
Thanks
GeneralRe: Just What I NeedmvpJosh Fischer26 Jul '10 - 3:36 
I'm glad you found it useful.
Josh Fischer

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 5 Mar 2009
Article Copyright 2008 by Josh Fischer
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid