(4 votes)

Layout controls in Silverlight 2 Beta 1

3 comments   /   posted by   Nikolay Raychev on Apr 07, 2008

Update: The source codes and the information in this article are compatible with Silverlight 2 Beta 2.

Introduction

Layout controls are Silverlight controls which act as containers of other controls. Their main purpose is the positioning and arranging of their child controls. There are 3 layout controls: Canvas, StackPanel and Grid.
Update: In Silverlight 2 beta 2 a new layout control called TabPanel is introduced. There are also four more descendants of the Panel Class: DataGridCellsPresenter, DataGridColumnHeadersPresenter, DataGridDetailsPresenter, DataGridRowsPresenter. Their purpose is the positioning of elements in a DataGrid template. They are not standalone controls.

See also:
Canvas Article
StackPanel Article
Grid Article

Overview

All layout controls derive from the basic abstract class Panel. They inherit the Children collection of type UIElementCollection. Since all elements in this collection are UIElement objects and the Panel itself derives from UIElement layout controls can be nested in one another without limitation.

The following example demonstrates the nesting:

Note: to understand this example you should be familiar with all layout controls: Canvas, StackPanel and Grid

We want to have the following meaningless result (I don’t like giving real world examples, I just want to show you how nesting of layout controls works.):

Here is the XAML code:

Update: The namespaces in Silverlight 2 beta 2 are changed:

<UserControl x:Class="LayoutControls.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">

 

<UserControl x:Class="LayoutControls.Page"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <Grid x:Name="grRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="100"></RowDefinition>
            <RowDefinition Height="100"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="300"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <StackPanel Background="Aqua" x:Name="spSecondRow" Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
            <Canvas Width="50" Height="100">
                <Button Content="Click" Canvas.Left="10" Canvas.Top="10" Canvas.ZIndex="0"></Button>
                <Button Content=":)" Canvas.Left="20" Canvas.Top="30" Canvas.ZIndex="1"></Button>
            </Canvas>
            <Canvas Width="50" Height="100">
                <Button Content="Click" Canvas.Left="10" Canvas.Top="10" Canvas.ZIndex="0"></Button>
                <Button Content=":)" Canvas.Left="20" Canvas.Top="30" Canvas.ZIndex="1"></Button>
            </Canvas>
            <Canvas Width="50" Height="100">
                <Button Content="Click" Canvas.Left="10" Canvas.Top="10" Canvas.ZIndex="0"></Button>
                <Button Content=":)" Canvas.Left="20" Canvas.Top="30" Canvas.ZIndex="1"></Button>
            </Canvas>
            <Canvas Width="50" Height="100">
                <Button Content="Click" Canvas.Left="10" Canvas.Top="10" Canvas.ZIndex="0"></Button>
                <Button Content=":)" Canvas.Left="20" Canvas.Top="30" Canvas.ZIndex="1"></Button>
            </Canvas>
            <Canvas Width="50" Height="100">
                <Button Content="Click" Canvas.Left="10" Canvas.Top="10" Canvas.ZIndex="0"></Button>
                <Button Content=":)" Canvas.Left="20" Canvas.Top="30" Canvas.ZIndex="1"></Button>
            </Canvas>
            <Canvas Width="50" Height="100">
                <Button Content="Click" Canvas.Left="10" Canvas.Top="10" Canvas.ZIndex="0"></Button>
                <Button Content=":)" Canvas.Left="20" Canvas.Top="30" Canvas.ZIndex="1"></Button>
            </Canvas>
        </StackPanel>
        <StackPanel Background="Yellow" x:Name="spThirdRow" Grid.Row="2" Grid.Column="1" Orientation="Horizontal">
            <Canvas Width="100" Height="100">
                <Rectangle Canvas.Top="10" Canvas.Left="45" Canvas.ZIndex="0" Fill="Lime"  Width="10" Height="80"></Rectangle>
                <Ellipse Canvas.Top="30" Canvas.Left="20" Canvas.ZIndex="1" Fill="Red" Width="60" Height="40"></Ellipse>
            </Canvas>
            <Canvas Width="100" Height="100">
                <Rectangle Canvas.Top="10" Canvas.Left="45" Canvas.ZIndex="0" Fill="Lime"  Width="10" Height="80"></Rectangle>
                <Ellipse Canvas.Top="30" Canvas.Left="20" Canvas.ZIndex="1" Fill="Red" Width="60" Height="40"></Ellipse>
            </Canvas>
            <Canvas Width="100" Height="100">
                <Rectangle Canvas.Top="10" Canvas.Left="45" Canvas.ZIndex="0" Fill="Lime"  Width="10" Height="80"></Rectangle>
                <Ellipse Canvas.Top="30" Canvas.Left="20" Canvas.ZIndex="1" Fill="Red" Width="60" Height="40"></Ellipse>
            </Canvas>
        </StackPanel>
    </Grid>
</UserControl>

We have a Grid, two StackPanels in the Grid and several Canvases in every StackPanel and several controls in every Canvas. You can put another Grid in the existing for example, or in a StackPanel or Canvas. It depends on the result you want to achieve.

You saw that we put a Background property of the two StackPanels. You can set it in the XAML as an attribute using one of the Colors enumeration but you also can use a Brush object for it. The following examples demonstrates its use with several different brushes:

Using the ImageBrush for a Grid Background:

XAML:

Update: The namespaces in Silverlight 2 beta 2 are changed:

<UserControl x:Class="GridBackground.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="400">

 

<UserControl x:Class="GridBackground.Page"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="400">
    <Grid x:Name="grMain" ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.Background>
            <ImageBrush x:Name="backgroundImageBrush" Stretch="UniformToFill">
                <ImageBrush.ImageSource>
                    <BitmapImage x:Name="bmpBackground" UriSource="http://terraristic.net/ photos/Pachydactylus_bibroni/Pachydactylus_bibroni_couple.jpg">
                    </BitmapImage>
                </ImageBrush.ImageSource>
            </ImageBrush>
        </Grid.Background>
    </Grid>
</UserControl>

Using the LinearGradientBrush for a StackPanel Background:

XAML:

Update: The namespaces in Silverlight 2 beta 2 are changed:

<UserControl x:Class="StackPanelBackground.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
 

 

<UserControl x:Class="StackPanelBackground.Page"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
    <StackPanel x:Name="spLayout">
        <Button Margin="30" Width="200" Content="I'm first"></Button>
        <Button Margin="30" Width="200" Content="I'm second"></Button>
        <Button Margin="30" Width="200" Content="I'm third"></Button>
        <StackPanel.Background>
            <LinearGradientBrush x:Name="backgroundLinearGradientBrush" MappingMode="RelativeToBoundingBox" StartPoint="0,0" EndPoint="1,1">
                <LinearGradientBrush.GradientStops>
                    <GradientStop Color="Red" Offset="0" />
                    <GradientStop Color="Orange" Offset="0.167" />
                    <GradientStop Color="Yellow" Offset="0.333" />
                    <GradientStop Color="Green" Offset="0.5"/>
                    <GradientStop Color="Blue" Offset="0.667" />
                    <GradientStop Color="Indigo" Offset="0.833" />
                    <GradientStop Color="Violet" Offset="1" />
                </LinearGradientBrush.GradientStops>
            </LinearGradientBrush>
        </StackPanel.Background>
    </StackPanel>
</UserControl> 

Using the RadialGradientBrush for a Canvas Background:

XAML:

Update: The namespaces in Silverlight 2 beta 2 are changed:

<