如何在控件模板中覆盖属性?

7

我有以下的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>

因为Fill="Red",显然所有的按钮都会有红色的填充/背景颜色。我想将此模板用于多个按钮,但每个按钮都有不同的填充颜色,在设计时已知。设置背景颜色没有效果,所以我必须改变Fill颜色,但我不能在实际按钮定义中重新定义Path属性。如何在XAML中访问和覆盖此属性?

2个回答

9

不要直接使用模板。分配一个样式并使用它。

<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>

然后像这样使用它:
<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>

你忘记设置红色按钮的背景属性了。 - JDB
谢谢,已添加背景属性的setter作为默认值。 - Joachim Kerschbaumer
1
谢谢,那个有效。 Florian Gl的解决方案也有效且代码更少——使用哪一个有什么好处?直接使用模板而非样式会有什么缺点吗? - Hackworth
@Hackworth - 声明样式的优点在于可以在样式中提供默认值,因此消费者只需要在从默认值更改属性时指定属性。WPF模板如何提供默认值,请参见第<Setter Property="Background" Value="Red" />行。如果您不需要这个功能,则直接使用模板即可。 - ToolmakerSteve

4
使用 TemplateBinding 在控件的 xaml 中更改模板的值:
                <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>

您的按钮:
                <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" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接