Making a button with vector graphics in content

Goran picture Goran · Sep 4, 2012 · Viewed 7k times · Source

I am pretty new with WPF design (and design in general), and I need help with one task.

I have a style for a button that contains some data in a Path, which draws an icon on it (basically simple add new icon). Now I would like to make a copy icon out of it.

I could not find a way to manipulate with Path I have in Blend, so what I had in mind was:

1) Copy Path data so we can draw two icons (to have two Path objects in Content) 2) Shift first a little to the left and top 3) Shift second a little to the right and bottom 4) Make second one overlap first one

This is what I did: Since we cannot have two elements set for Content, I have added one Grid element, and inside I copied Path element twice. Then I repositioned both path to simulate duplicate data.

<Setter Property="Content">
    <Setter.Value>
    <Grid>
            <Path Data="..." Margin="10" Stretch="Fill" Fill="{StaticResource IconBrush}" RenderTransformOrigin="0.5,0.4">
                <Path.RenderTransform>
                    <TransformGroup>
                <ScaleTransform />
                <SkewTransform />
                <RotateTransform Angle="-90" />
                <TranslateTransform />
            </TransformGroup>
        </Path.RenderTransform>
    </Path>
    <Path Data="..." Margin="10" Stretch="Fill" Fill="{StaticResource IconBrush}" RenderTransformOrigin="0.5,0.6">
                <Path.RenderTransform>
            <TransformGroup>
                <ScaleTransform />
                <SkewTransform />
                <RotateTransform Angle="-90" />
                <TranslateTransform />
            </TransformGroup>
        </Path.RenderTransform>
    </Path>                                 
    </Grid>
    </Setter.Value>
</Setter>

Problem: I do not get overlap with second icon (basically everything is transparent. That means that I probsably need to delete some points on first icon, but I could not achieve that in Blend?

Can anyone share some light how to achieve what I need?

Answer

Stewbob picture Stewbob · Sep 4, 2012

Not sure what your icons should look like, but the following XAML will display two overlapping plus signs using the same Path data for both, but with a simple TranslateTransform to offset the second one.

    <Grid>
        <Path Fill="#FF008000" >
            <Path.Data>
                <PathGeometry Figures="m 30 25.362188 0 30.000001 -30 0 0 20 30 0 0 29.999991 20 0 0 -29.999991 30 0 0 -20 -30 0 0 -30.000001 -20 0 z" FillRule="nonzero"/>
            </Path.Data>
        </Path>
        <Path Fill="#FF92D050" >
            <Path.Data>
                <PathGeometry Figures="m 30 25.362188 0 30.000001 -30 0 0 20 30 0 0 29.999991 20 0 0 -29.999991 30 0 0 -20 -30 0 0 -30.000001 -20 0 z" FillRule="nonzero"/>
            </Path.Data>
            <Path.RenderTransform>
                <TranslateTransform X="25" Y="-25"/>
            </Path.RenderTransform>
        </Path>
    </Grid>

I would recommend not putting margins or 'Stretch' properties in your actual path objects. Take care of that in the Grid container they are in, or a containing Viewbox if you need to scale them up or down.

EDIT

If you are actually using the Fill property of the Path object to draw the icon geometry, as with a VisualBrush object, instead of the Path.Data, then you don't want to use a Path in the first place. Just use two Rectangle objects, with your 'IconBrush' Fill in the grid and do the TranslateTransform on one of them so that they overlap to the desired amount. Remember that with XAML, the object that appears last in the listing is rendered on top.

EDIT 2

    <Grid>
        <Path Fill="#FFFFFFFF">
            <Path.Data>
                <PathGeometry Figures="m 13.123027 65.796864 0 81.448876 133.750213 0 0 -133.778725 -67.192062 0 z" FillRule="NonZero"/>
            </Path.Data>
        </Path>
        <Path Fill="#FFB3B3B3">
            <Path.Data>
                <PathGeometry Figures="M 79.624708 0.36218262 0 62.950511 l 0 97.411669 160 0 0 -159.99999738 -80.375292 0 z m 2.28303 16.89635038 61.172792 0 0 126.207297 -126.161061 0 0 -76.829978 0.187646 -0.156158 64.800623 0 0 -49.221161 z" FillRule="NonZero"/>
            </Path.Data>
        </Path>
        <Path Fill="#FFFFFFFF">
            <Path.Data>
                <PathGeometry Figures="m 13.123027 65.796864 0 81.448876 133.750213 0 0 -133.778725 -67.192062 0 z" FillRule="NonZero"/>
            </Path.Data>
            <Path.RenderTransform>
                <TranslateTransform X="30" Y="30"/>
            </Path.RenderTransform>
        </Path>
        <Path Fill="#FFB3B3B3">
            <Path.Data>
                <PathGeometry Figures="M 79.624708 0.36218262 0 62.950511 l 0 97.411669 160 0 0 -159.99999738 -80.375292 0 z m 2.28303 16.89635038 61.172792 0 0 126.207297 -126.161061 0 0 -76.829978 0.187646 -0.156158 64.800623 0 0 -49.221161 z" FillRule="NonZero"/>
            </Path.Data>
            <Path.RenderTransform>
                <TranslateTransform X="30" Y="30"/>
            </Path.RenderTransform>
        </Path>
    </Grid>

The above XAML is probably way too big for your needs. You can just put the whole grid in a Viewbox and then set the Height and Width properties of the Viewbox to get it to the size you need.



EDIT 3

Custom button style:

<Style x:Key="btnCustom" TargetType="{x:Type Button}">
    <Setter Property="Content">
        <Setter.Value>
            <Viewbox>
                <Grid Margin="0,0,30,30">
                    <Path Fill="#FFFFFFFF">
                        <Path.Data>
                            <PathGeometry Figures="m 13.123027 65.796864 0 81.448876 133.750213 0 0 -133.778725 -67.192062 0 z" FillRule="NonZero"/>
                        </Path.Data>
                    </Path>
                    <Path Fill="#FFB3B3B3">
                        <Path.Data>
                            <PathGeometry Figures="M 79.624708 0.36218262 0 62.950511 l 0 97.411669 160 0 0 -159.99999738 -80.375292 0 z m 2.28303 16.89635038 61.172792 0 0 126.207297 -126.161061 0 0 -76.829978 0.187646 -0.156158 64.800623 0 0 -49.221161 z" FillRule="NonZero"/>
                        </Path.Data>
                    </Path>
                    <Path Fill="#FFFFFFFF">
                        <Path.Data>
                            <PathGeometry Figures="m 13.123027 65.796864 0 81.448876 133.750213 0 0 -133.778725 -67.192062 0 z" FillRule="NonZero"/>
                        </Path.Data>
                        <Path.RenderTransform>
                            <TranslateTransform X="30" Y="30"/>
                        </Path.RenderTransform>
                    </Path>
                    <Path Fill="#FFB3B3B3">
                        <Path.Data>
                            <PathGeometry Figures="M 79.624708 0.36218262 0 62.950511 l 0 97.411669 160 0 0 -159.99999738 -80.375292 0 z m 2.28303 16.89635038 61.172792 0 0 126.207297 -126.161061 0 0 -76.829978 0.187646 -0.156158 64.800623 0 0 -49.221161 z" FillRule="NonZero"/>
                        </Path.Data>
                        <Path.RenderTransform>
                            <TranslateTransform X="30" Y="30"/>
                        </Path.RenderTransform>
                    </Path>
                </Grid>
            </Viewbox>
        </Setter.Value>
    </Setter>
</Style>

Button implementation:

    <Button HorizontalAlignment="Right" Style="{StaticResource btnCustom}"
            Height="30" Width="100"/>

What it looks like in the WPF Window:

enter image description here