#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,017 – Scaling Items in a List Using a Slider

Below is an example of using a Slider control to scale a bunch of images in an ItemsControl.  The images are displayed within a WrapPanel.  As they are resized, the WrapPanel automatically updates the layout, so that the number of rows needed to display the images changes.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ScrollViewer>
            <ItemsControl ItemsSource="{Binding ActorList}" Margin="20">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Image Source="{Binding Image}" Height="100">
                            <Image.LayoutTransform>
                                <ScaleTransform ScaleX="{Binding Value, ElementName=sliScale}"
                                                ScaleY="{Binding Value, ElementName=sliScale}"/>
                            </Image.LayoutTransform>
                        </Image>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </ScrollViewer>
        <Slider Name="sliScale" Grid.Row="1" Margin="10,5"
                Minimum="0.1" Maximum="3"
                Value="1.0"/>
    </Grid>

1017-001

 

1017-002

1017-003

#768 – Scaling Transforms

You can use a scaling transform to scale a user interface element in the X or Y dimensions.  Scaling an element increases or reduces its size.  You can specify separate scaling in the X and Y dimensions.

A value of 1.0 represents the normal (not scaled) size of the element.  Scale values larger than 1.0 increase the size of the element and values less than 1.0 decrease its size.

You specify scaling using a ScaleTransform element, setting values for the ScaleX and ScaleY properties.  If you don’t supply a scale value for one of the dimensions (X or Y), a value of 1.0 is used.

Here’s a simple example:

    <StackPanel Orientation="Vertical">
        <Button Content="Push Me" HorizontalAlignment="Center" Padding="10,5" Margin="5"/>
        <Button Content="Push Me" HorizontalAlignment="Center" Padding="10,5" Margin="5">
            <Button.LayoutTransform>
                <ScaleTransform ScaleX="2.0"/>
            </Button.LayoutTransform>
        </Button>
        <Button Content="Push Me" HorizontalAlignment="Center" Padding="10,5" Margin="5">
            <Button.LayoutTransform>
                <ScaleTransform ScaleY="2.0"/>
            </Button.LayoutTransform>
        </Button>
        <Button Content="Push Me" HorizontalAlignment="Center" Padding="10,5" Margin="5">
            <Button.LayoutTransform>
                <ScaleTransform ScaleX="0.7" ScaleY="0.7"/>
            </Button.LayoutTransform>
        </Button>
    </StackPanel>

767-001

#752 – Tracking Total Scale when Scaling by Touch Manipulation

When you use touch manipulation events to scale an element, you typically read the Scale property of the ManipulationDelta object passed in to the ManipulationDelta event handler.   This property reports a delta scaling value to apply to the element, derived from the user’s touch manipulation (e.g. pinch/expand).

For example, a scale value of 1.05 says “scale the object 5% larger than it was the last time that this event was fired”.

In the code example below, we also track total scale, relative to the original size of the element.  (Note that we don’t actually scale the element here).

        private Vector totalScale = new Vector(1.0, 1.0);

        private void Image_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
        {
            ManipulationDelta md = e.DeltaManipulation;
            Vector scale = md.Scale;

            totalScale.X *= scale.X;
            totalScale.Y *= scale.Y;

            Console.WriteLine(string.Format(
                "Scale: X={0}, Y={1}, TotalScale: X={2}, Y={3}",
                scale.X, scale.Y, totalScale.X, totalScale.Y));

            e.Handled = true;
        }

752-001

#24 – Don’t Use Bitmaps in WPF Applications

Because WPF is able to scale your application based on the system DPI, you should avoid using bitmaps in your application.  Instead, you should render all controls, e.g. buttons on a toolbar, with vector graphics so that they can be scaled larger/smaller and still look correct.

The hardest part of this process will be finding vector-based graphical images to use in your application and then converting them to XAML so that you can use them in your WPF project.

Mike Swanson has written a plug-in for Adobe Illustrator that allows exporting vector-based images to XAML (which you can then import directly into a WPF project).  There’s also a good writeup explaining the process here.

Here’s an example, showing an image of the Earth that scales when the application window scales.