This article is compatible with the latest version of Silverlight.
Introduction
The Grid is a layout control used as a container for other Silverlight controls. It acts like a table in HTML but there are many differences in the markup representation.
Overview
The following example demonstrates how to use a Grid and how to create rows and columns:
We want to have the following table structure:
The most important thing about the Grid is how to define its RowDefinitions and ColumnDefinitions collections and how to specify to which row and column every control in the Grid belongs.
Here is the XAML code:
<UserControl x:Class="Grid2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="grdLayoutRoot" Background="White" Width="400" Height="300" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button x:Name="btnTest" Width="50" Height="30" Content="Text" Grid.Row="0" Grid.Column="0"></Button>
<Rectangle x:Name="rectBlue" Width="50" Height="30" Fill="Blue" Grid.Row="2" Grid.Column="1"></Rectangle>
</Grid>
</UserControl>
Note: We set the ShowGridLines="True" This indicates that the grid lines will be visible. You can always set this property to False if you want to hide the grid lines.
For every row in the Grid we have a RowDefinition element. All row definitions are enclosed in a Grid.RowDefinitions element. Our first two rows are 50 pixels high and Height of the third one is set to “*”. This indicates that the row will take the whole place in the Grid which is not taken by the other rows.
Respectively for every column in the Grid we have a ColumnDefinition element. All column definitions are enclosed in a Grid.ColumnDefinitions element. Our first two columns are 100 pixels wide and the last one is 50px. The third column takes the free space because its width is set to “*”.
We can also use proportional sizing for both columns and rows. For example we can set the column sizes as follows:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="5*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
Thus our columns will be in a proportion 2:2:5:1 and the user control will look like this:
You can adjust the proportions of the row heights in the same way.
Another option is to set the width and/or the height to “auto”. This way every column/row changes its size so as to match the width/height of the controls in it. For example:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
Omitting the width and/or height properties makes all columns and rows the same size:
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
In comparison with HTML the items in the markup are outside the row definitions and column definitions. For every control in the table you can set the attached properties Grid.Row and Grid.Column to indicate the index of the row and column where the control will be placed. We have two controls in our table, one Button and one Rectangle. The button is placed in the first row (index 0) and the first column (index 0). The rectangle is placed in the third row and the second column.
Instead of setting the exact width for every column and height for every row you can use the alternative MinWidth / MaxWidth and MinHeight / MaxHeight properties. The following example demonstrates it:
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="30" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition Width="Auto" MinWidth="30" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition Width="Auto" MinWidth="30" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition Width="Auto" MinWidth="30" MaxWidth="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button x:Name="btnTest" Width="200" Height="30" Content="Text" Grid.Row="0" Grid.Column="0"></Button>
<Rectangle x:Name="rectBlue" Width="50" Height="30" Fill="Blue" Grid.Row="2" Grid.Column="1"></Rectangle>
You see that the first column takes its MaxWidth 150 pixels in spite of the fact that the Button in it is 200 pixels wide. You also see that the third column takes its MinWidth though there is nothing in it.
Please be careful using these properties because they depend on the neighboring columns/rows. The following example demonstrates it:
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="30" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition MinWidth="30" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition MinWidth="30" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition MinWidth="30" MaxWidth="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
Removing the “Auto” width from the second, third and fourth column results in the following:
It seems that the MinWidth and MaxWidth are not taken into consideration at all.
They also depend on the combination of properties in the current column/row.
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="30" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition Width="Auto" MinWidth="30" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition Width="Auto" MinWidth="30" MaxWidth="150"></ColumnDefinition>
<ColumnDefinition Width="Auto" MinWidth="30" MaxWidth="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button x:Name="btnTest" Width="200" Height="30" Content="Text" Grid.Row="0" Grid.Column="0"></Button>
<Rectangle x:Name="rectBlue" Width="50" Height="30" Fill="Blue" Grid.Row="2" Grid.Column="1"></Rectangle>
We just put an Auto Width for the first column too and the result is the following:
It seems that the MinWidth for the third column works but the MaxWidth for the first column does not with Auto width.
So just be careful using these properties.
What we can do if we want our button to be placed is several cells?
Another opportunity that you have is to set the Grid.ColumnSpan and Grid.RowSpan attached properties for every control in the Grid.
<Button Grid.ColumnSpan="2" Grid.RowSpan="2" x:Name="btnTest" Width="50" Height="30" Content="Text" Grid.Row="0" Grid.Column="0"></Button>
This acts just like the colspan and rowspan attributes of the HTML table cell with the difference that in Silverlight we set these properties to the control. The cool thing here is that these properties act per control and don’t make the table cell bigger. We can put other controls without these two properties and it will be positioned the way it has to be. For example we can put a TextBlock in the first cell:
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="tblSomeText" Text="Some Text" Grid.Row="0" Grid.Column="0"></TextBlock>
Have you noticed the two new properties of the TextBlock we just added - the horizontal and vertical alignment of the control according to the cell boundaries? We omitted them in the Button and the Rectangle because they are set to “Center” by default for them.
You can get or set the “Grid.Row”, “Grid.Column”, “Grid.RowSpan” and “Grid.ColumnSpan” attached properties programatically using the static methods of the Grid class.
The following example demonstrates it:
Code behind:
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
Grid.SetColumn( this.btnTest, 1 );
Grid.SetRow( this.btnTest, 1 );
Grid.SetColumnSpan( this.btnTest, 2 );
Grid.SetRowSpan( this.btnTest, 2 );
}
}
XAML:
<Grid x:Name="grdLayoutRoot" Background="White" Width="400" Height="300" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button x:Name="btnTest" Width="50" Height="30" Content="Click" Grid.Row="0" Grid.Column="0"></Button>
</Grid>
Result:
Here is another example where we get these properties and increase them:
Grid.SetColumn( this.btnTest, Grid.GetColumn( this.btnTest ) + 1 );
Grid.SetRow( this.btnTest, Grid.GetRow( this.btnTest ) + 1 );
Grid.SetColumnSpan( this.btnTest, Grid.GetColumnSpan( this.btnTest ) + 1 );
Grid.SetRowSpan( this.btnTest, Grid.GetRowSpan( this.btnTest ) + 1 );
The result is the same.
Conclusion
This article is just a brief description of the key features of the Grid control. It targets the developer who has just started with the Silverlight controls. Any comments are welcome.
Reference
http://silverlight.net/learn/tutorials.aspx
http://msdn2.microsoft.com/en-us/library/system.windows.controls.grid(VS.95).aspx