7

I have the following XAML:

<Window x:Class="WpfTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="227" Width="391">
    <Window.Resources>
        <ControlTemplate x:Key="PentagonButton" TargetType="{x:Type Button}">
            <Grid>
                <Path Data="M 0,-1 L -.95,-.3 L -.58,.8 L .58,.8 L .95,-.3 Z" Stroke="Black" Stretch="Uniform" Fill="Red" />
                <Viewbox>
                    <ContentPresenter Margin="20" />
                </Viewbox>
            </Grid>
        </ControlTemplate>
    </Window.Resources>
    <Grid>
        <Button Content="red" Margin="12,19,0,0" Template="{StaticResource PentagonButton}" HorizontalAlignment="Left" Width="166" Height="151" VerticalAlignment="Top" />        
        <Button Content="blue" Margin="178,19,0,0" Template="{StaticResource PentagonButton}" Height="151" VerticalAlignment="Top" HorizontalAlignment="Left" Width="173" />        
    </Grid>
</Window>

Because of Fill="Red", obviously all buttons will have a red fill/background color. I want to use this template for several buttons, but each of them with a different fill color, known at design time. Setting the background color has no effect, so I have to change the Fill color, but I can't define the Path property again in the actual button definitions. How do I access and override this property in the XAML?

Hackworth
  • 1,069
  • 2
  • 9
  • 23

2 Answers2

9

Don´t use the template directly. Assign a Style and use that.

i.e.

<Style x:Key="PentagonButton" TargetType="{x:type Button}">
    <Setter Property="Background" Value="Red"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid>
                    <Path Data="M 0,-1 L -.95,-.3 L -.58,.8 L .58,.8 L .95,-.3 Z" Stroke="Black" Stretch="Uniform" Fill="{TemplateBinding Background}" />
                    <Viewbox>
                        <ContentPresenter Margin="20" />
                    </Viewbox>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Then use it like this:

<Grid>
    <Button Content="red" Margin="12,19,0,0" Style="{StaticResource PentagonButton}" HorizontalAlignment="Left" Width="166" Height="151" VerticalAlignment="Top" />        
    <Button Content="blue" Margin="178,19,0,0" Style="{StaticResource PentagonButton}" Height="151" VerticalAlignment="Top" HorizontalAlignment="Left" Width="173" Background="Blue" />        
</Grid>
AntikM
  • 636
  • 4
  • 13
  • 28
Joachim Kerschbaumer
  • 9,695
  • 7
  • 49
  • 84
  • You forgot to set the red button's Background property. – JDB Jan 08 '13 at 14:52
  • thanks, added setter for background property as default value – Joachim Kerschbaumer Jan 08 '13 at 14:54
  • 1
    Thanks, that works. Florian Gl's solution works as well and has less code - what is a good reason to use one over the other? Are there drawbacks to using a template directly, instead of a style? – Hackworth Jan 08 '13 at 15:15
  • @Hackworth - advantage of declaring a style is that you can provide a *default* value in the style, so consumer only needs to specify property when they are changing from default. [WPF template How to provide default value](https://stackoverflow.com/q/1793611/199364), see line ``. If you don't need this, then its fine to use template directly. – ToolmakerSteve Mar 17 '19 at 08:52
4

Use TemplateBinding to change the values of your templates in the xaml of its controls:

                <ControlTemplate x:Key="PentagonButton" TargetType="{x:Type Button}">
                    <Grid>
                        <Path Data="M 0,-1 L -.95,-.3 L -.58,.8 L .58,.8 L .95,-.3 Z" Stroke="Black" Stretch="Uniform" Fill="{TemplateBinding Background}" />
                        <Viewbox>
                            <ContentPresenter Margin="20" />
                        </Viewbox>
                    </Grid>
                </ControlTemplate>

Your button:

                <Button Background="Red" Content="red" Margin="12,19,0,0" Template="{StaticResource PentagonButton}" HorizontalAlignment="Left" Width="166" Height="151" VerticalAlignment="Top" />
                <Button Background="Blue" Content="blue" Margin="178,19,0,0" Template="{StaticResource PentagonButton}" Height="151" VerticalAlignment="Top" HorizontalAlignment="Left" Width="173" />
Florian Gl
  • 5,984
  • 2
  • 17
  • 30