ARTICLE

WPF/Silverlight Layouts

Posted by Diptimaya Patra Articles | Silverlight with C# May 20, 2009
Page Layouts in WPF and Silverlight 2 or Silverlight 3
Reader Level:

Introduction

PANEL: Base class for all elements that provide layout.

HANDLES:

  • Base sizing and positioning.

  • Alignment, Margins and padding.

  • Z-index.

User Interface Panels

Panel Name

X - Dimension

Y - Dimension

Canvas

Constrained to Content

Constrained to Content

Stack Panel(Vertical/Default)

Constrained

Constrained to Content

Stack Panel (Horizontal)

Constrained to Content

Constrained

Dock Panel

Constrained

Constrained

Wrap Panel

Constrained to Content

Constrained to Content

Uniform Grid

Constrained

Constrained

Grid

Constrained

Constrained (Except when Auto)

Canvas

  • Canvas is the simplest layout included in WPF.

  • Canvas offers four properties: Top, Left, Right, and Bottom.

  • Canvas lets us position its child elements at any offset from one corner of the panel.

  • Only two properties can be used: one horizontal coordinate and one vertical coordinate.

  • Canvas doesn't place any interesting constraints on the width or height of the layout slot, so the HorizontalAlignment and VerticalAlignment properties are irrelevant.

  • ClipToBounds="True": This is a property which gives us the visibility of the controls inside the bound of the Canvas.

    Example: Canvas

    Canvas.gif

    Figure 1.1 Layouts: Canvas: Basic Positioning

      <Canvas Width="400" Height="300" Background="LightBlue">
        <Button
    Canvas.Top="2" Canvas.Left="2">Top, Left</Button>
        <Button
    Canvas.Top="2" Canvas.Right="2">Top, Right</Button>
        <Button 
    Canvas.Bottom="2" Canvas.Left="2">Bottom, Left</Button>
        <Button 
    Canvas.Bottom="2" Canvas.Right="2">Bottom, Right</Button>
        <Button 
    Canvas.Top="120" Canvas.Left="120" Canvas.Bottom="120" Canvas.Right="120">Top120, Left120, Bottom120, Right120</Button>
      </Canvas>

    Canvas1.gif

    Figure 1.2 Layouts: Canvas: Overtaking Controls

      <XAML Code>

      <Canvas Width="400" Height="300" Background="LightBlue">    <Button Canvas.Top="2" Canvas.Left="2">Top, Left</Button>
        <Button
    Canvas.Top="10" Canvas.Left="40">Top, Right</Button>
        <Button 
    Canvas.Bottom="2" Canvas.Left="2">Bottom, Left</Button>
        <Button 
    Canvas.Bottom="2" Canvas.Right="2">Bottom, Right</Button>
        <Button 
    Canvas.Top="120" Canvas.Left="120" Canvas.Bottom="120" Canvas.Right="120">Top120, Left120, Bottom120, Right120</Button>
      </Canvas>

    Stack Panel

    • As the name implies, StackPanel stacks things up in a row.

    • Through the Orientation property we can control whether the stack is horizontal or vertical.

    • Default orientation of StackPanel is Vertical.

    • The slot for each child in StackPanel is given the entire width or height of the control (depending on its orientation).

    • StackPanel determines its preferred size according to the maximum size of its children.

    • StackPanel must be used carefully because it measures children using an infinite width or height based on the orientation.

    • specifically causing problems for TextBlock with wrapping and ScrollViewer.

    Example: Stack Panel

    StackPanel.gif

    Figure 1.3 Layouts: StackPanel : Orientation Vertical(default) & Horizontal.

    <XAML Code>

     <StackPanel Background="LightBlue" Width="300" Height="400" Orientation="Horizontal">
      <Button>
    Button1</Button>
      <Button>
    Button2</Button>
      <Button>
    Button3</Button>
      <Button>
    Button4</Button>
      <Button>
    Button5</Button>
      </StackPanel>

    Dock Panel
     

    • DockPanel is fairly similar to StackPanel, except that it allows mixing of stacking from different edges within the same layout container.

    • DockPanel is probably one of the most common UI layouts today.

    • Windows Forms natively supported docking.

    • Docking allows elements to be stacked at any edge of a container, with the final element filling the remaining space.

    • Implementing this layout in WPF is relatively simple: The DockPanel offers a single property, Dock, which allows us to specify the edge to which a controlis docked.

    • The declaration order of the elements determines the order in which they're placed, and by default the last child fills the remaining space.

    Example: Dock Panel

    DockPanel.gif

    Figure 1.3 Layouts: DockPanel: Mocking Windows Explorer Layout

    <XAML Code>

    <DockPanel Height="600" Width="600">
      <Button
    DockPanel.Dock='Top'>Menu Area (Dock=Top)</Button>
      <Button
    DockPanel.Dock='Top'>Toolbar Area (Dock=Top)</Button>
      <Button
    DockPanel.Dock='Left'>Folders (Dock=Left)</Button>
      <Button>
    Content (Fills remaining space becauseLastChildFill='true')</Button>
    </DockPanel>

    Wrap Panel
     

    • If DockPanel is a stack panel with multiple edges, then WrapPanel is a stack panel with wrapping support.

    • WrapPanel, on the other hand, uses the available space and fits elements to it; and when it runs out of room, it wraps to the next line. (Example: Toolbar Layout)

    • By default, WrapPanel simply sizes all the children to fit their content.

    • Although we can fix the width and height of the children by using the ItemWidth and ItemHeight properties.

    Example: Wrap Panel

    WrapPanel.gif

    Figure 1.4 Layouts: WrapPanel: Mocking Toolbar buttons

    <XAML Code>

    <WrapPanel Background="LightBlue" Width="400" Height="300">
      <Button>
    One</Button>
      <Button>
    Two</Button>
      <Button>
    Three</Button>
      <Button>
    Four</Button>
      <Button>
    Five</Button>
      <Button>Six</Button>

    WrapPanel1.gif

    Figure 1.5 Layouts: WrapPanel: Mocking Toolbar buttons (Defining ItemWidth and ItemHeight)

    <XAML Code>

     <WrapPanel Background="LightBlue" Width="400" Height="300" ItemHeight="20" ItemWidth="50">
      <Button>
    One</Button>
      <Button>
    Two</Button>
      <Button>
    Three</Button>
      <Button>
    Four</Button>
      <Button>
    Five</Button>
      <Button>Six</Button>

    Uniform Grid
     

    • The final basic layout, which is really nothing like StackPanel, is UniformGrid.

    • UniformGrid provides a very basic grid layout: Each cell is the same size (hence uniform), and the locations of the items are determined simply by their order in the children collection.

    • To use UniformGrid, we specify the number of columns and rows we want. If we specify only columns, then rows will be calculated as the number of children divided by the number of columns, and vice versa.

    • The width of each cell is calculated as the maximum of all child widths, and the height of each cell is the maximum of all child heights.

    • If we provide more children than can be displayed (e.g., adding a seventh button to the preceding example), it will be positioned as if the grid had infinite height (the Seven button will be directly below the Five button).

    • It is important, but odd, that UniformGrid has positioned the last child outside the bounds of the control.

    Example: Uniform Grid

    UniformGrid.gif

    Figure 1.6 Layouts: Uniform Grid

    <XAML Code>

    <UniformGrid Columns="2" Rows="3" Background="LightBlue" Height="200" Width="200">
      <Button>
    One</Button>
      <Button>
    Two</Button>
      <Button>
    Three</Button>
      <Button>
    Four</Button>
      <Button>
    Five</Button>
      <Button>
    Six</Button>
    </UniformGrid>

    Grid

    • Grid is by far the most power, flexible, and complex of the UI layouts.

    • On the surface, Grid is simple: Elements are positioned within grid cells defined by a series of rows and columns.

    • The simplest use of Grid is to set the RowDefinitions and ColumnDefinitions properties, add some children, and use the Grid.Row and Grid.Column attached properties to specify which child goes in which slot.

    • There are 3 big concepts associated with Grid:
       

      1. Separation of layout from structure
         

        • Because the row and column information for Grid is based on property values, we can greatly modify the layout without changing the order of the elements.

        • Therefore, not only is it much easier to change the layout, but the order of the elements does not depend on the layout order, so it is also much easier to control overlapping and predict what overlapping will do.
           

      2. Flexible sizing models
         

        • Most layout panels partition the space using either the content size of the child, or the absolute value of the size of the child. In addition to these common modes, Grid introduces the notion of percentage sizing, in which the width or height of a column or row can be specified with a star (*) unit.

        • Stars allow columns and rows to occupy a percentage of the space in the grid, after any size to content or absolute sizing of columns and rows is done.
           

      3. Shared size information
         

        • Shared sizing is the last major capability that is built into Grid.

        • A grid shares sizing information among all the controls that are positioned in the same column.

        • In the simplest form, this allows a set of controls to all have the same size, but be wide enough for the largest control.

      Example: Grid

      Grid.gif

      Figure 1.7 Layouts: A Complex Grid

      <XAML Code>

               <Grid Background="LightBlue">
                    <Grid.ColumnDefinitions>
                           <ColumnDefinition
      Width="0.02*"/>
                           <ColumnDefinition
      Width="0.102*"/>
                           <ColumnDefinition
      Width="0.102*"/>
                           <ColumnDefinition
      Width="0.103*"/>
                           <ColumnDefinition
      Width="0.122*"/>
                           <ColumnDefinition
      Width="0.102*"/>
                           <ColumnDefinition
      Width="0.102*"/>
                           <ColumnDefinition
      Width="0.082*"/>
                           <ColumnDefinition
      Width="0.224*"/>
                           <ColumnDefinition
      Width="0.041*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                           <RowDefinition
      Height="0.014*"/>
                           <RowDefinition
      Height="0.057*"/>
                           <RowDefinition
      Height="0.014*"/>
                           <RowDefinition
      Height="0.608*"/>
                           <RowDefinition
      Height="0.014*"/>
                           <RowDefinition
      Height="0.282*"/>
                           <RowDefinition
      Height="0.011*"/>
                    </Grid.RowDefinitions>
                    <Button
      Content="1" Grid.Column="1" Grid.Row="1"/>
                    <Button
      Content="2" Grid.Column="2" Grid.Row="1"/>
                    <Button
      Content="3" Grid.Column="3" Grid.Row="1"/>
                    <Button
      Content="4" Grid.Column="4" Grid.Row="1"/>
                    <Button
      Content="5" Grid.Column="5" Grid.Row="1"/>
                    <Button
      Content="6" Grid.Column="6" Grid.Row="1"/>
                    <Button
      Content="7" Grid.Column="7" Grid.Row="1"/>
                    <Button
      Content="One" Grid.Column="1" Grid.ColumnSpan="6" Grid.Row="3"/>
                    <Button
      Content="Two" Grid.Column="1" Grid.ColumnSpan="6" Grid.Row="5" Margin="0,0,0,-0.226"/>
                    <Button
      Content="Three" Grid.Column="8" Grid.Row="3"/>
                    <Button
      Content="Four" Grid.Column="8" Grid.Row="5"/>
                    <Button
      Content="Six" Grid.Column="7" Grid.Row="3" Grid.RowSpan="3"/>
             </Grid>

COMMENT USING