Search code examples
wpfxamlsvgcanvas

Scaling Canvas Resource in ViewBox


I'm trying to get a reusable SVG image into WPF.

I have a merged dictionary which contains an entry for an external xaml file which contains a canvas, which in turn came from an SVG file. It has a structure like:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Canvas x:Key="myImage" Name="myImage" Width="110" Height="35">
        <Canvas.RenderTransform>
            <TranslateTransform X="0" Y="0"/>
        </Canvas.RenderTransform>
        <Canvas.Resources/>
        <Canvas Name="layer1">
            <Canvas.RenderTransform>
                <TranslateTransform X="-51.393708" Y="-16.078911"/>
            </Canvas.RenderTransform>
            <Ellipse...

Note the Canvas width and height are specified here.

To get this to appear in a Window, I add this to my window's resources:

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="XamlResources/myImage.xaml"/>
</ResourceDictionary.MergedDictionaries>
...
<Viewbox Width="200" Stretch="Uniform" HorizontalAlignment="Left">
    <Canvas Width="110"  Height="35">
        <StaticResource ResourceKey="myImage"/>
    </Canvas>
</Viewbox>

Note that the Canvas width and height are again specified here.

My question is, why do I need to specify the canvas size (110x35) in both the resource and the window control? If I remove the one in the window to have:

<Canvas Width="110"  Height="35">
    <StaticResource ResourceKey="myImage"/>
</Canvas>

...then the image disappears.

Am I doing something fundamentally wrong with trying to get a reusable SVG image into WPF?


Solution

  • Note that the Canvas width and height are again specified here.

    No, you are creating a new Canvas that wraps the other one that is defied your resource dictionary.

    If you want to use the myImage resource directly, you should reference it like this:

    <StaticResource ResourceKey="myImage"/>
    

    Then you don't need to specify the size more than once.

    But to be able to reuse the resource in more than one place, you should set the x:Shared attribute of the resource to false to prevent the same Canvas instance form being reused:

    <Canvas x:Key="myImage" x:Shared="false" ... />