#808 – How Shape Elements Are Positioned within a Canvas

The different Shape elements (e.g. Ellipse, Line, Path, Polygon, Polyline or Rectangle) describe a shape to be drawn using an X,Y coordinate system, with X increasing from left to right and Y increasing from top to bottom.

When you add Shape elements to a Canvas, the coordinates specified for the elements are used to determine the element’s position within the coordinate space of the Canvas.  For example, a point in a shape at (0,0) would be located in the upper left corner of the Canvas.

    <Canvas Margin="10" Background="AliceBlue">
        <Polygon Points="10,10 60,60 60,100 140,80 120,40"
                 Stroke="DarkViolet" StrokeThickness="2"/>
    </Canvas>

808-001
If you set any of attached properties for positioning with the Canvas (Left, Top, Right, Bottom), these properties will be used to offset the entire shape, relative to one (or more) of the sides of the canvas.

    <Canvas Margin="10" Background="AliceBlue">
        <Polygon Canvas.Left="50" Canvas.Bottom="0"
                 Points="10,10 60,60 60,100 140,80 120,40"
                 Stroke="DarkViolet" StrokeThickness="2"/>
    </Canvas>

808-003

#807 – Setting the Position of Child Elements in a Canvas from Code

Recall that you position child elements in a Canvas panel by setting at most two out of four of the following attached properties: Left, Right, Top, Bottom.  In all cases, you set a property to a value expressed in WPF (device-independent) units, equivalent to 1/96 inch.

You set any of these four values from code using one of the following static methods of the Canvas property:

  • Canvas.SetLeft
  • Canvas.SetRight
  • Canvas.SetTop
  • Canvas.SetBottom
        // Whenever we move mouse over label, put it somewhere else
        private void Label_MouseMove(object sender, MouseEventArgs e)
        {
            Label lbl = sender as Label;
            Canvas canv = lbl.Parent as Canvas;

            Random rand = new Random();

            // Set position to random location
            Canvas.SetLeft(sender as UIElement,
                           rand.Next((int)(canv.ActualWidth - lbl.ActualWidth)));
            Canvas.SetTop(sender as UIElement,
                          rand.Next((int)(canv.ActualHeight - lbl.ActualHeight)));
        }

#806 – Setting ZIndex Values of Child Elements in a Canvas from Code

You use the Canvas.ZIndex attached property on a child element in a Canvas to indicate the relative positioning of elements, when they happen to overlap.  Elements that have higher ZIndex values will appear on top of elements having lower values.

        <Button Content="1 - Lft10,Top10" Canvas.Left="10" Canvas.Top="10"
                Canvas.ZIndex="4"/>
        <Button Content="2 - Rt10,Top10" Canvas.Right="10" Canvas.Top="15"
                Canvas.ZIndex="3"/>
        <Button Content="3 - Lft10,Bott10..." Canvas.Left="15" Canvas.Bottom="15"
                Canvas.ZIndex="2"/>
        <Button Content="4 - Rt10,Bott10" Canvas.Right="10" Canvas.Bottom="8"
                Canvas.ZIndex="1"
                Click="Button_Click"/>

806-001
As with other attached properties, you can set the value from code by using a static method of the form SetPropName.  In the case of ZIndex, you use the static Canvas.SetZIndex method, passing in a reference to child control.

private void Button_Click(object sender, RoutedEventArgs e)
{
    Canvas.SetZIndex(sender as UIElement, 5);
}

#740 – Set Background of Canvas to Transparent to Receive Touch Events

If you define one or more touch event handlers for a Canvas panel, without setting any other properties, you may not see any touch events for the canvas.

This happens because none of the controls inheriting from Panel will receive either touch or mouse events unless you specify a value for the panel’s Background property.  So, to receive touch events for the Canvas, you can just set its Background property to Transparent.

    <Canvas Name="canvMain" Background="Transparent"
        TouchDown="Canvas_TouchDown" TouchMove="Canvas_TouchMove" TouchUp="Canvas_TouchUp">
    </Canvas>

#479 – Using a Layout Transform on Child Elements in a Canvas

You can use a LayoutTransform on child elements of a Canvas to transform them graphically.  Specifically, you can use a RotateTransform, ScaleTransform or SkewTransform.  (Translation transforms are ignored).

    <Canvas>
        <Button Content="Hopalong Cassidy" Canvas.Left="10" Canvas.Top="10">
            <Button.LayoutTransform>
                <RotateTransform Angle="45"/>
            </Button.LayoutTransform>
        </Button>
        <Button Content="Roy Rogers" Canvas.Right="10" Canvas.Top="10">
            <Button.LayoutTransform>
                <TransformGroup>
                    <ScaleTransform ScaleX="2.0"/>
                    <RotateTransform Angle="-45"/>
                </TransformGroup>
            </Button.LayoutTransform>
        </Button>
        <Button Content="Spade Cooley" Canvas.Left="10" Canvas.Bottom="10">
            <Button.LayoutTransform>
                <SkewTransform AngleX="20"/>
            </Button.LayoutTransform>
        </Button>
    </Canvas>

#478 – Two Out of Four Margin Values Are Used for Elements in a Canvas

When adding child elements to a Canvas panel, you can specify at most two of the four attached properties: Top, Left, Bottom, Right.  This places the child element relative to one of the four corners of the Canvas.

Child elements can have values for their Margin property, but only two of the four possible sub-values are used.  The two parts of the margin used are based on the two Canvas attached properties that are being used.

For example, if you position a child element using the Canvas.Bottom and Canvas.Left properties, then only the Bottom and Left portions of the child element’s Margin are used.  The Top and Right margins are ignored.

Margin values that are used are added to the canvas positioning properties.

<Canvas>
    <Button Content="Left=10, Margin.Left=0" Canvas.Left="10" Canvas.Top="10" Margin="0,0,0,0"/>
    <Button Content="Left=10, Margin.Left=15" Canvas.Left="10" Canvas.Top="40" Margin="15,0,0,0"/>
</Canvas>

#477 – Default ZIndex Value for Child Elements of a Canvas

You can set the Canvas.ZIndex attached property for a child element of the Canvas panel, to dictate the overlap behavior of child elements.  Elements with a higher ZIndex value will appear on top of elements with a lower value.

By default, all child elements of a Canvas have a ZIndex value of 0.  In this case, the Canvas lays out the child elements in the order that they exist in the Children collection (the same order in which they appear in XAML), with elements occurring later in the collection layering on top of elements that occur earlier in the collection.

More generally, any time that two elements have the same value for ZIndex, they are layered in the order in which the appear in the Children collection.


#476 – Set ZIndex Values for Child Elements of Canvas

By default, child elements of a Canvas panel will be arranged in the order that they appear in a XAML file, with later elements appearing on top of earlier elements.

You can override this behavior by specifying explicit values for the Canvas.ZIndex attached property.  An element with a higher ZIndex value will appear on top of an element with a lower value.

        <Canvas Name="canv" Grid.Row="0">
            <Button Content="1 - Lft10,Top10" Canvas.Left="10" Canvas.Top="10" Canvas.ZIndex="4"/>
            <Button Content="2 - Rt10,Top10" Canvas.Right="10" Canvas.Top="15" Canvas.ZIndex="3"/>
            <Button Content="3 - Lft10,Bott10..." Canvas.Left="15" Canvas.Bottom="15" Canvas.ZIndex="2"/>
            <Button Content="4 - Rt10,Bott10" Canvas.Right="10" Canvas.Bottom="8"  Canvas.ZIndex="1"/>
        </Canvas>

#475 – Child Elements in Canvas Can Overlap

It’s possible for child elements of a Canvas to overlap each other, depending on their position.  In the example below, the Canvas contains four Button controls, each located relative to one of the four corners of the Canvas.  As the parent window is resized, it eventually gets small enough for the child elements to overlap.

When child elements in a Canvas overlap, their order is based on the order in which they were added to the Canvas.  If the elements were all specified in XAML, the first elements listed will be at the bottom of overlapped elements and the last elements will be at the top.

    <Canvas>
        <Button Content="1 - Lft10,Top10" Canvas.Left="10" Canvas.Top="10"/>
        <Button Content="2 - Rt10,Top10" Canvas.Right="10" Canvas.Top="15"/>
        <Button Content="3 - Lft10,Bott10..." Canvas.Left="15" Canvas.Bottom="15"/>
        <Button Content="4 - Rt10,Bott10" Canvas.Right="10" Canvas.Bottom="8"/>
    </Canvas>

#473 – Positioning Child Elements in a Canvas

Child elements are position in a Canvas panel by specifying the location of the child element in WPF units.

You can position all elements by specifying values for Left and Top properties only.  This will position each element relative to the upper left corner of the container.

These child elements will then retain the same position from the upper left corner of the container as it is resized.

You can specify a child element’s position relative to any of the four corners of the container, depending on which two of the four positioning properties you specify.  Child elements will then retain their position relative to that corner as the container is resized.

  • Left/Top - upper left corner
  • Right/Top - upper right corner
  • Right/Bottom - lower right corner
  • Left/Bottom - lower bottom corner
    <Canvas>
        <Button Content="Left=10,Top=10" Canvas.Left="10" Canvas.Top="10"/>
        <Button Content="Right=10,Top=10" Canvas.Right="10" Canvas.Top="10"/>
        <Button Content="Right=10,Bottom=10" Canvas.Right="10" Canvas.Bottom="10"/>
        <Button Content="Left=10,Bottom=10" Canvas.Left="10" Canvas.Bottom="10"/>
    </Canvas>


Follow

Get every new post delivered to your Inbox.

Join 233 other followers