views:

498

answers:

3

Hi,

I am exploring the idea of using professionally designed vector images as the ControlTemplates in my WPF application. The idea is to make several types of controls, each with a different visual design, which can then be dragged and dropped. This is exactly the same use-case as a visual designer (a'la visio)

I have the following XAML. It defines a control template with a target type of Button, and I have a Button which uses this template. What I want to know is how can I modify this template so that it will use only the height and width of the Button. It seems to me as if the Template renders itself relative to the top-left corner of the button (If I move the button the image moves) but it takes no account of the dimensions of the button, so it keeps its "designed" size no matter what I do.

<Window x:Class="Euphrosyne.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
    <ControlTemplate TargetType="{x:Type Button}" x:Key="PresentBox">

        <Canvas Name="svg2" >
            <Canvas.Resources/>
            <Canvas Name="layer1">
                <Path Name="path2385" Fill="#D45500" Stroke="#FF000000" StrokeThickness="1px" StrokeLineJoin="Miter" StrokeEndLineCap="Flat" Data="M 110 82.362183 A 40 30 0 1 1 39.041709 63.365048 L 70 82.362183 z"/>
                <Path Name="path2387" Fill="#FF0000" Data="M 100 100 L 79.96762 89.419767 L 59.895213 99.923868 L 63.767267 77.602471 L 47.574559 61.758424 L 69.999999 58.543274 L 80.064762 38.247014 L 90.052393 58.581339 L 112.46547 61.881608 L 96.212721 77.664061 L 100 100 z"/>
                <Path Name="path2389" Fill="#C83737" Data="M 100 40.000002 L 97.601178 65.149257 L 116.9586 81.382849 L 92.298963 86.872981 L 82.841672 110.29944 L 70 88.543275 L 44.797648 86.788031 L 61.520697 67.85185 L 55.402078 43.340588 L 78.579163 53.393551 L 100 40.000002 z">
                    <!--path-->
                </Path>
            </Canvas>
        </Canvas>

    </ControlTemplate>
</Window.Resources>
<Grid>
    <Button Template="{StaticResource PresentBox}" >Hi there</Button>
</Grid>
</Window>
A: 

You could set the Path.RenderTransform to a custom ScaleTransform to scale the sub elements to parent width/height.

kek444
+1  A: 

Wrap the Canvas in a Viewbox. The Canvas does not correlate its own dimensions with those of its content. Hence you can see the content move with the Canvas, but not resize. A Viewbox augments the Canvas's behavior by stretching its content when its own dimensions change. You can control the Viewbox's behavior, e.g. stretch horizontally, vertically or both. Unfortunately, there's no limo stretching, which would have been nice for UI controls.

Here's how it might look. Note that I am guessing as for the width and height. They should match those of the actual path. You should also make sure the path is flushed against the X and Y axes, to avoid leaving unintended margins.

<Viewbox Name="viewbox1"
         Height="200" Width="200"
         HorizontalAlignment="Left" VerticalAlignment="Top"
         Stretch="Fill">
    <Canvas Name="layer1">
        <Path Name="path2385" Fill="#D45500" Stroke="#FF000000" StrokeThickness="1px" StrokeLineJoin="Miter" StrokeEndLineCap="Flat" Data="M 110 82.362183 A 40 30 0 1 1 39.041709 63.365048 L 70 82.362183 z"/>
        <Path Name="path2387" Fill="#FF0000" Data="M 100 100 L 79.96762 89.419767 L 59.895213 99.923868 L 63.767267 77.602471 L 47.574559 61.758424 L 69.999999 58.543274 L 80.064762 38.247014 L 90.052393 58.581339 L 112.46547 61.881608 L 96.212721 77.664061 L 100 100 z"/>
        <Path Name="path2389" Fill="#C83737" Data="M 100 40.000002 L 97.601178 65.149257 L 116.9586 81.382849 L 92.298963 86.872981 L 82.841672 110.29944 L 70 88.543275 L 44.797648 86.788031 L 61.520697 67.85185 L 55.402078 43.340588 L 78.579163 53.393551 L 100 40.000002 z"/>
    </Canvas>
</Viewbox>
Oren Trutner
+1  A: 

Generally Canvas doesn't respect the Size of the parent control, so if you replace Canvas with Grid you can get the Button size on to the Paths inside the controltemplate.

    <Grid x:Name="layer1" Width="Auto" Height="Auto">
    <Path x:Name="path2385" Fill="#D45500" Stroke="#FF000000" StrokeThickness="1px" StrokeLineJoin="Miter" StrokeEndLineCap="Flat" Data="M 110 82.362183 A 40 30 0 1 1 39.041709 63.365048 L 70 82.362183 z" Margin="0,0,6.459,49.147" d:LayoutOverrides="Width, Height"/>
    <Path x:Name="path2387" Fill="#FF0000" Data="M 100 100 L 79.96762 89.419767 L 59.895213 99.923868 L 63.767267 77.602471 L 47.574559 61.758424 L 69.999999 58.543274 L 80.064762 38.247014 L 90.052393 58.581339 L 112.46547 61.881608 L 96.212721 77.664061 L 100 100 z" Margin="0,0,4.493,62" d:LayoutOverrides="Width, Height"/>
    <Path x:Name="path2389" Fill="#C83737" Data="M 100 40.000002 L 97.601178 65.149257 L 116.9586 81.382849 L 92.298963 86.872981 L 82.841672 110.29944 L 70 88.543275 L 44.797648 86.788031 L 61.520697 67.85185 L 55.402078 43.340588 L 78.579163 53.393551 L 100 40.000002 z" Margin="0,0,0,51.7" d:LayoutOverrides="Width, Height">
     <!--path-->
    </Path>
 </Grid>

Or else you can use TemplateBinding, which can give Button's properties to the controltemplate. for example.

 Height="{TemplateBinding Height}" Width="{TemplateBinding Width}">

And if you cant remove Canvas at all then use a ViewBox around it as Oren suggests above

Jobi Joy
where is the d xml namespace in the d:LayoutOverrides="Width, Height" coming from?
Pieter Breed
Sorry that was inserted by my Expression blend edit :)
Jobi Joy