#1,062 – Scaling a Canvas Using a ViewBox

ViewBox is typically used to scale a panel containing other elements.  One common use of a ViewBox is to scale the contents of a Canvas panel.

We might include several elements within a Canvas that has an explicit size.

1062-001

If we re-size the window, however, the canvas stays the same size.

1062-002

We could have had the Canvas stretch to fill the remaining area, but its elements would still be the same size.

We can get the elements within the Canvas to scale by wrapping the Canvas in a ViewBox.

    <DockPanel>
        <Label DockPanel.Dock="Top" Background="LightGray"
               Content="Stuff at top of window here"
               VerticalAlignment="Top"/>
        <Label DockPanel.Dock="Bottom" Background="AliceBlue"
               Content="Bottom stuff down here"
               VerticalAlignment="Bottom"/>
        <Viewbox>
            <Canvas Background="Bisque" Width="200" Height="100">
                <Line X1="5" Y1="5" X2="195" Y2="95"
                        Stroke="Black"/>
                <Label Canvas.Left="80" Canvas.Top="5" Content="Howdy"/>
                <Ellipse Height="30" Width="50" Stroke="Blue" StrokeThickness="2"
                            Canvas.Left="140" Canvas.Top="5"/>
            </Canvas>
        </Viewbox>
    </DockPanel>

Now when we resize the window, everything within the Canvas is scaled.
1062-003

 

Advertisements

#1,061 – Scaling Content Using a ViewBox

You can scale entire panels by embedding the panel to be scaled within a ViewBox.

Assume that you start with a simple StackPanel in a Window (the StackPanel scales up to fit in the Window).

1061-001

If you want to scale these elements larger as the window gets larger, you can place the StackPanel in a ViewBox.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Scaling" Width="220" Height="140">
    <Viewbox>
        <StackPanel Background="Bisque">
            <Label Margin="5" Background="AliceBlue"
              Content="Alice Isn't Blue Anymore"/>
            <Button Content="Got It"
              HorizontalAlignment="Center"/>
            <TextBox Margin="5"
                  Text="Enter something here"/>
        </StackPanel>
    </Viewbox>
</Window>

Everything is a little bigger now, within the original window. This is because the StackPanel is no longer stretching to fill the Window, but sizing to fit its contents. And the ViewBox is then scaling the StackPanel to fit into the Window.

1061-002

Now scaling the Window larger causes everything within the ViewBox to scale up.

1061-003

 

#1,060 – Clipping in Grid Happens Before Render Transforms

Layout and render transforms fit into the layout logic for panels as follows:

  • Layout transforms are performed
  • Panel calculates layout of child elements (and clips or resizes)
  • Render transforms are performed

Clipping and/or resizing of elements happens after layout transforms have been applied.  This means that the layout-transformed object is clipped/resized to fit into the Grid.  You can, however, applied a render transform to an object to allow it to extend outside the bounds of the Grid, because this step happens after clipping/resizing.

Below, the first button is rotated before layout, so the rotated button is sized to fit into the Grid cell.  The second button is rotated after layout, so is not resized.

    <Grid ShowGridLines="True" Background="Bisque"
          Margin="10" ClipToBounds="false">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Button Content="Click Here Please"
                HorizontalAlignment="Center"
                VerticalAlignment="Center">
            <Button.LayoutTransform>
                <RotateTransform Angle="30"/>
            </Button.LayoutTransform>
        </Button>

        <Button Grid.Row="1" Content="Click Here Please"
                Width="100"
                VerticalAlignment="Center">
            <Button.RenderTransform>
                <RotateTransform Angle="30"/>
            </Button.RenderTransform>
        </Button>
    </Grid>

1060-001

#1,059 – Clipping vs. Resizing in a Grid

Grid appears to clip its child elements, in that the elements are constrained to fit within a particular grid cell.

In reality, however, a Grid is often resizing, rather than clipping, the child elements.  If the child element does not specify an explicit size, the Grid will ask the child to be a smaller size, rather than simply clipping it at the grid cell boundary.

Below, the top Button does not have an explicit width, but the bottom Button does.  As we shrink the Grid, the top button will be resized, while the bottom button will be clipped.  The labels indicate the actual button widths.

    <Grid ShowGridLines="True" Background="Bisque"
          Margin="10" ClipToBounds="false">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label Content="{Binding ElementName=myButton, Path=ActualWidth}"/>
        <Button Name="myButton" Margin="2"
                Grid.Column="1" Content="Click Here Please"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"/>

        <Label Grid.Row="1" Content="{Binding ElementName=myButton2, Path=ActualWidth}"/>
        <Button Name="myButton2" Margin="2"
                Grid.Row="1" Grid.Column="1" Content="Click Here Please"
                Width="100"
                VerticalAlignment="Center"/>
    </Grid>


1059-001
1059-002

#1,058 – Translation Makes No Sense within Layout Transforms

layout transform is a transformation applied before a container’s child elements are laid out.

Because the container will position child elements after doing the layout transform, it doesn’t make sense to include a translation as part of a layout transform.  The container positions its child elements based on its layout rules, deciding on the X and Y position of each element after you’ve done the layout transform.

If you want to translate an element relative to where the container wants to put it, you can do that by using the Margin property of the element or by applying a render transform.

Below, the second label uses a translate transform that is ignored.  The third label does the translation in the render transform.

    <StackPanel>
        <Label Content="Flavius" Background="AliceBlue"
               HorizontalAlignment="Left"/>
        <Label Content="Lucius" Background="Bisque"
               HorizontalAlignment="Left">
            <Label.LayoutTransform>
                <TranslateTransform X="100"/>
            </Label.LayoutTransform>
        </Label>
        <Label Content="Constantine" Background="Gainsboro"
               HorizontalAlignment="Left">
            <Label.RenderTransform>
                <TranslateTransform X="100"/>
            </Label.RenderTransform>
        </Label>
    </StackPanel>

1058-001

#1,057 – Preventing a Grid from Clipping a Child Element

Grid will normally clip child elements within each grid cell so that the element will not extend beyond the bounds of the cell.  In the example below, the Label in the second column is clipped to the right side of the column.

    <Grid Background="AliceBlue" Margin="25" ShowGridLines="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Label Grid.Column="1"
                Content="Each man delights in the work that suits him best." Background="Olive"
                VerticalAlignment="Center"
                Margin="10"/>
    </Grid>

1057-001
If we want to prevent the Grid from clipping the element, we can do this by placing the element in a Canvas, which we then put into the Grid.  Because a Canvas does not clip child elements,  this will allow the element to extend beyond the boundaries of the Grid.

    <Grid Background="AliceBlue" Margin="25" ShowGridLines="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Canvas Grid.Column="1">
            <Label Content="Each man delights in the work that suits him best." Background="Olive"
                   VerticalAlignment="Center"
                   Margin="10"/>
        </Canvas>
    </Grid>

1057-002

#1,056 – Grid Clips Child Elements

While a Canvas panel does not clip its child elements, a Grid does clip child elements.  The child elements are clipped even if you set the ClipToBounds property of the Grid to false.

        <Grid Background="AliceBlue" Margin="25" >
            <Label Content="Each man delights in the work that suits him best." Background="Olive"
                   VerticalAlignment="Center" 
                   Margin="10"/>
        </Grid>

1056-001
1056-002