This article is compatible with the latest version of Silverlight.
In response to Joe’s comment on the Canvas article about how the Canvas control deals with the Measure/Arrange process when it is laid out by a parent Panel:
It seems that during Measure/Arrange process the child Canvas will take zero width and height provided these properties are not set, even if it contains some controls. Here is a little example:
XAML:
<UserControl x:Class="CanvasInCanvas.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Canvas x:Name="cnvControlHolder" Background="White" Height="300" Width="400">
<Canvas x:Name="cnvInner" Canvas.Top="10" Canvas.Left="10" Background="Blue">
<Button x:Name="btnHello" Content="Hello Joe :)" Canvas.Top="0" Canvas.Left="0" Margin="10"></Button>
</Canvas>
</Canvas>
</UserControl>
We don’t see the Blue background of the inner Canvas because its size is zero.
Setting Width and Height properties work in the expected manner:
<Canvas x:Name="cnvControlHolder" Background="White" Height="300" Width="400">
<Canvas x:Name="cnvInner" Canvas.Top="10" Canvas.Left="10" Width="200" Height="100" Background="Blue">
<Button x:Name="btnHello" Content="Hello Joe :)" Canvas.Top="0" Canvas.Left="0" Margin="10"></Button>
</Canvas>
</Canvas>
What about setting Width and Height bigger than these of the outer Canvas?
<Canvas x:Name="cnvControlHolder" Background="White" Height="300" Width="400">
<Canvas x:Name="cnvInner" Canvas.Top="10" Canvas.Left="10" Width="450" Height="350" Background="Blue">
<Button x:Name="btnHello" Content="Hello Joe :)" Canvas.Top="0" Canvas.Left="0" Margin="10"></Button>
</Canvas>
</Canvas>
The inner Canvas takes exactly the space it wants to take, and this does not depend on its parent control’s size.
There is a little difference when we put a Canvas in a StackPanel.
<StackPanel x:Name="LayoutRoot" Background="White" Width="400" Height="300">
<Canvas x:Name="cnvInner" Width="450" Height="50" Background="Blue">
<Button x:Name="btnHello" Content="Hello Joe :)" Canvas.Top="0" Canvas.Left="0" Margin="10"></Button>
</Canvas>
</StackPanel>
By default the orientation of the StackPanel is Vertical. We see that the Canvas takes its desired width which is bigger than the StackPanel’s width.
What about bigger height?
<StackPanel x:Name="LayoutRoot" Background="White" Width="400" Height="300">
<Canvas x:Name="cnvInner" Width="450" Height="50" Background="Blue">
<Button x:Name="btnHello" Content="Hello Joe :)" Canvas.Top="0" Canvas.Left="0" Margin="10"></Button>
</Canvas>
</StackPanel>
The height is cut to the StackPanel’s height.
Changing the orientation of the StackPanel to Horizontal causes the width of the Canvas to be cut to the StackPanel’s width.
<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" Background="White" Width="400" Height="300">
<Canvas x:Name="cnvInner" Width="450" Height="50" Background="Blue">
<Button x:Name="btnHello" Content="Hello Joe :)" Canvas.Top="0" Canvas.Left="0" Margin="10"></Button>
</Canvas>
</StackPanel>
I’ll give several examples about the behavior of the Canvas when positioned in a Grid.
<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True" Width="400" Height="300">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Canvas x:Name="cnvInner" Grid.Row="1" Grid.Column="1" Background="Blue">
<Button x:Name="btnHello" Content="Hello Joe :)" Canvas.Top="0" Canvas.Left="0" Margin="10"></Button>
</Canvas>
</Grid>
We did not specify the Width and Height of the Canvas so it took the whole available space.
Specifying the Width and Height of the Canvas makes it take exactly the desired space, no matter whether the Canvas will come out of the Grid cell or of the entire Grid:
<Grid x:Name="LayoutRoot" Background="White" ShowGridLines="True" Width="400" Height="300">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Canvas x:Name="cnvInner" Width="300" Height="230" Grid.Row="1" Grid.Column="1" Background="Blue">
<Button x:Name="btnHello" Content="Hello Joe :)" Canvas.Top="0" Canvas.Left="0" Margin="10"></Button>
</Canvas>
</Grid>
This behavior will vary depending on the Width / MinWidth / MaxWidth properties of the ColumnDefinition element and the Height / MinHeight / MaxHeight properties of the RowDefinition element. Some examples about combination of these properties are given in the Grid article.