#497 – Use a UniformGrid to Make a Group of Buttons the Same Size

You can use a StackPanel to make its child elements the same size in one of its dimensions.  This is harder to do in the other dimension.

The example below uses a StackPanel to contain some buttons.  They end up the same height, but are still different widths.

You can make the buttons the same height and width using a UniformGrid instead of a StackPanel.

        <UniformGrid DockPanel.Dock="Bottom" Margin="10" Rows="1" HorizontalAlignment="Right"
                    VerticalAlignment="Bottom">
            <Button Grid.Column="0" Content="No" FontSize="18" Margin="5" Padding="6,3"/>
            <Button Grid.Column="1" Content="Yes, Absolutely" Margin="5" Padding="6,3"/>
            <Button Grid.Column="2" Content="Maybe" Margin="5" Padding="6,3"/>
        </UniformGrid>

The UniformGrid will make sure that each cell is the same height and the same width.  This is desirable because you then avoid having to set the button sizes manually.

#496 – Using a StackPanel to Make a Group of Buttons the Same Size

You’ll often want to stack a group of buttons in a GUI, vertically or horizontally.  You’d typically use a StackPanel to do this.

Let’s say that you want a series of buttons stacked vertically on the right side of a window.

We can use a DockPanel as the main container and add a StackPanel docked on the right and oriented vertically.  But when we do this, the StackPanel expands to fill the available space, as does each Button.

The HorizontalAlignment of the StackPanel defaults to Stretch, as do each of the buttons.  We could set the HorizontalAlignment for each Button to Right, but the buttons now all size to fit their content, which is not quite what we want.

What we really want is for the HorizontalAlignment of each Button to be Stretch, but for the HorizontalAlignment of the StackPanel itself to be Right.  This gives us what we want.

#492 – Layout Can Change at Runtime

One benefit of flow-based layout, as opposed to coordinate-based layout, is that elements in the user interface will size to fit their content.  The GUI designer does not have to explicitly set the size and location of each child element.

The layout containers in WPF don’t just position their child elements at design-time, but will re-measure and arrange their child elements when certain properties of the child elements change.  For example, if the Content property of a Label control changes, the parent container will update its layout based on the new text.

In the example below, when the Label containing the movie title changes, the buttons to its right shift.

    <StackPanel>
        <Label Content="Have you seen this movie?" Margin="3"/>
        <StackPanel Orientation="Horizontal">
            <Label Content="{Binding NextMovieTitle}" Margin="3"/>
            <Button Content="Seen It" Margin="3"/>
            <Button Content="NOT Seen It" Margin="3"/>
        </StackPanel>
        <Button Content="Next Movie" HorizontalAlignment="Center" Margin="3"
                Click="btnNext_Click"/>
    </StackPanel>


#480 – ZIndex Values and Render Transforms

It’s possible for controls to overlap each other when using a RenderTransform–even in containers that don’t normally overlap their child controls.

In the example below, the first Button in a StackPanel is rotated and ends up overlapping the second Button.

    <StackPanel Margin="10">
        <Button Content="Alpha" HorizontalAlignment="Center" Padding="20,0" >
            <Button.RenderTransform>
                <RotateTransform Angle="45"/>
            </Button.RenderTransform>
        </Button>
        <Button Content="Bravo" HorizontalAlignment="Center" Padding="20,0" />
    </StackPanel>


Whenever overlapping occurs, the containing panel’s attached ZIndex property dictates the overlapping order of the child controls. With default ZIndex values of 0, child controls appearing later in the XAML are rendered on top of earlier controls.

You can explicitly control the overlap order by specifying ZIndex values.  In the previous example, if we give the first button a ZIndex of 2 and the second button a ZIndex of 1, their overlap order is reversed.

#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 110 other followers