This is something I’ve been doing since we first got LayoutRoot, and it has saved me aggravation a number of times. This works in Silverlight 2 and Silverlight 3 (the drop shadow effect in the example below only works in Silverlight 2).
Simply put: I never set column definitions, margins or anything else related to layout directly on layout root. Instead, I nest another grid inside it and work with that.
I was asked if I consider this a preference or a best practice. Given the iterative approach we usually take to designing and developing our apps, I would say this definitely falls under the best practice category.
Here’s an example of the nested grid approach. Note that I didn’t set margins, rows or columns on LayoutRoot.
<UserControl x:Class="PeteBrown.ScratchProject.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="350" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Content goes here -->
</Grid>
</Grid>
</UserControl>
This way, I can easily add a border or other elements later without having to move everything around. Consider the case where you put together this app, and decide you want to put a border around the content. If you defined all the columns and rows directly on layout root, you’d either need to move them all to a second grid now, or make the border the LayoutRoot. But if you made the border LayoutRoot and had code expecting LayoutRoot to be a panel, then you’d have to fix that as well.
Say you wanted to add an interesting background rectangle to your layout. If you set the rows/columns/margins on layout root, you’d have to live within those (with an ugly RowSpan and ColumnSpan setting and negative margins) or again, move the grid down to another level.
Here’s an example of what I’m talking about. As I iterated through this, adding the columns, and then adding the background rectangle, I’d have had to do a lot of shifting if I attached everything directly to LayoutRoot.
<UserControl x:Class="PeteBrown.ScratchProject.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot">
<Rectangle x:Name="BackgroundRectangle"
RadiusX="5"
RadiusY="5"
Margin="10"
Fill="#FF323242">
<Rectangle.Effect>
<DropShadowEffect BlurRadius="20"
Direction="0"
Opacity="1"
ShadowDepth="0" />
</Rectangle.Effect>
</Rectangle>
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="350" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Content goes here -->
<TextBlock Text="Here lies the content. May she rest in peace."
FontSize="14"
Foreground="White"
TextWrapping="Wrap"/>
</Grid>
</Grid>
</UserControl>
Note above that the rectangle sits within LayoutRoot so I don’t have to fiddle with row and column spans, and don’t have to set negative margins. The content sits within the inside grid.
This also gives you the freedom to use something other than a grid (a canvas or stackpanel), while still keeping the LayoutRoot itself as a grid. This may be important to how your application is structured.