I've been playing with XAML a little bit lately, both the Silverlight and WPF flavors, and thought I would discuss some of the things I learned about the <Grid /> control and a few of the concepts I had issues with.
The first concept I had to grasp was the fact that <Grid /> is a visual layout control. It has nothing to do with data. This reminds me of the good ol' days when I was allowed to use tables to layout my HTML pages. I actually had to convince myself this is a good thing. Microsoft designed it for layout so I should use it for layout.
When you start adding rows and columns to a test grid you will find that the first row or column is 0 not 1. From a layout standpoint the first row or column should be 1, but if you look from the development side the RowDefinitions and ColumnsDefinitions properties are collections where the first index is 0. Looks like designers will have to get used to 0 based indexing, but I'm a dev so it's fine by me.
There are three ways to size a row or column of a grid.
- Give a hard size. This can be data bound also, but it's basically giving a hard number.
- "Auto". The row or column takes on the size of its content.
- "N*" (Star sizing). The new wonder of the development world. Takes up the space not used by the auto or hard sizing and splits it between all of the star sized rows or columns.
Auto and hard sizing are easy concepts, but star sizing threw me for a loop for a bit. The way I understand star sizing comes down to being a number of units of remaining space. You just need to add up the number of stars to determine the number of units of remaining space.
For example, in the following grid the first row will take up a set size. Now for the remaining space there are 2 star rows so there are 2 units of remaining space. Therefore, the second and third rows will each take up half of the remaining space.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
</Grid>
In this example there are 2 star rows but one uses 2 stars so there are 3 units of remaining space. So the first row takes up two thirds and second row gets one third of the remaining space.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
</Grid>
Another example I've seen is below. It makes it a little clearer to the reader that each of the rows is going to take up 50% of the remaining space.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
</Grid>
Just remember star sizes use the remaining space so having a lot of auto or hard sized rows or columns can leave you with very little space to split up.
Here are a couple of notes and things I don't want to forget:
This will make a nice base which will resize itself whenever the user changes the window size:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>
To put a control in row 0 and column 1 from XAML use the following:
<
Rectangle Grid.Row="0" Grid.Column="1" />
To put a control in row 0 and column 1 from code use the following:
myControl.SetValue(Grid.RowProperty, 0);
myControl.SetValue(Grid.ColumnProperty, 1);
myGrid.Children.Add(myControl)