Last Updated: February 25, 2016
·
8.755K
· thebringking

Scalable Graphics in XAML

When adding graphics and icons to your XAML based app (Silverlight, WPF, WP7, WP8 or WinRT) one design choice I commonly see made, and one that I made often, was to use png's for everything. There is a better way! XAML supports the basic elements for scalable graphics. Using the Shape class and its derived types. For example here is a simple button with and image set as its content:

Source a raster image

<Button Background="Transparent" Width="150" Height="75">
     <Image Source="/somepng.png"/>
</Button>

This method is quick, but what happens when that button is viewed on a hdpi device? If your source image is too small, the result might look terrible.

For simple graphics like this next arrow Picture, here is how I try and solve this problem:

Tools you will need

To create shape data in XAML, I use a couple of different tools:

*Expression Design

*Inkscape

Both of these tools can import SVG files, and then export or save the resulting file as XAML. Expression is a little better than Inkscape at producing valid XAML, however Inkscape is a more powerful drawing tool. Once you have created your XAML icon, you can create a style with that shape data.

Create a style targeting a ContentControl

<Style TargetType="ContentControl" x:Key="NextButtonScalable">
  <Setter Property="Template">
      <Setter.Value>
          <ControlTemplate TargetType="ContentControl">
            <Viewbox>
                <Canvas Width="50" Height="50">
                    <Path Data="M 19.285714 11.785714 7.4999997 18.5902 l -11.7857141 6.804485 0 -13.608971 0 -13.6089706 11.7857147 6.8044856 z" Fill="{TemplateBinding Foreground}"/>
                    <Path Data="M 19.285714 11.785714 7.4999997 18.5902 l -11.7857141 6.804485 0 -13.608971 0 -13.6089706 11.7857147 6.8044856 z" Fill="{TemplateBinding Foreground}"/>
                </Canvas>
            </Viewbox>
          </ControlTemplate>
      </Setter.Value>
  </Setter>
</Style>

The key to this working is that any shape controls inside of a ViewBox control, will scale to fill the ViewBox (ignoring the width and height set on the child canvas). Since the shapes are vector drawings, they will look great at any resolution.

Use your scalable control on a button

<Button Background="Transparent" Width="150" Height="75">
    <ContentControl Style="{StaticResource NextButtonScalable}"       Foreground="Black"/>
</Button>

A great thing about Shapes in XAML, is that you can change the color of your icon by setting the Foreground property of the ContentControl.

The resulting XAML using this method is a little heavier, however I feel like this method will become increasingly important as hdpi screens become the norm.