Skip Navigation LinksHome / Articles / View Article

How does the Canvas control deal with the Measure/Arrange process

+ Add to SilverlightShow Favorites
1 comments   /   posted by Nikolay Raychev on Apr 10, 2008
(0 votes)
Categories: Controls , Tutorials , QuickStarts

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.

Share


Comments

Comments RSS RSS
  • RE: How does the Canvas control deal with the Measure/Arrange process  

    posted by Kareem on Apr 24, 2010 20:41
    Thank you

Add Comment

 
 

   
  
  
   
Please add 4 and 5 and type the answer here:

Join the free SilverlightShow webcast 'Running Silverlight Outside the Browser and with Elevated Trust'. Sept 7th, 8 am - 9 am PDT.
In this live session Chris Anderson will cover configuring and debugging OOB mode, toast notifications, elevated trust, direct file access and much more.
Learn more | Register | See more webinars (hide this)