WPF中的参数化样式/模板?

时间:2010-08-06 16:27:02

标签: wpf

如果我有两个200行长的控制模板,它们只有几个字(几种颜色)不同,我怎么能让xaml重复使用?也就是说,不必复制粘贴模板并在200行中更改3个单词。

这是一个简化的例子。两种风格的唯一区别是边框颜色。那么我可以用某种方式定义ButtonStyle,使用参数化颜色,并从中继承BlackButtonStyle和GrayButtonStyle,并在BlackButtonStyle和GrayButtonStyle中仅指定该颜色吗?

alt text http://img444.imageshack.us/img444/9545/buttonstyles.png

<Window x:Class="WpfApplication33.Window1"
        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>

        <Style x:Key="BlackButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border BorderBrush="Black" BorderThickness="3">
                            <ContentControl Content="{TemplateBinding Content}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style x:Key="GrayButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border BorderBrush="Gray" BorderThickness="3">
                            <ContentControl Content="{TemplateBinding Content}"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    </Window.Resources>
    <StackPanel>
        <Button Content="Black Button"
                Style="{StaticResource BlackButtonStyle}"/>
        <Button Content="Gray Button"
                Style="{StaticResource GrayButtonStyle}"/>
    </StackPanel>
</Window>

以下是基于2个答案的代码。只需要在控件上设置样式,但不幸的是它仍然会混淆控件的标记:

<Window x:Class="WpfApplication33.Window1"
        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>

        <Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border Name="border"
                                BorderBrush="Black"
                                BorderThickness="3">
                            <ContentControl Content="{TemplateBinding Content}"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="Tag" Value="Gray">
                                <Setter TargetName="border"
                                        Property="BorderBrush"
                                        Value="Gray"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style x:Key="BlackButtonStyle"
               TargetType="{x:Type Button}"
               BasedOn="{StaticResource ButtonStyle}"/>
        <Style x:Key="GrayButtonStyle"
               TargetType="{x:Type Button}"
               BasedOn="{StaticResource ButtonStyle}">
            <Setter Property="Tag" Value="Gray"/>
        </Style>

    </Window.Resources>
    <StackPanel>
        <Button Content="Black Button"
                Style="{StaticResource BlackButtonStyle}"/>
        <Button Content="Gray Button"
                Style="{StaticResource GrayButtonStyle}"/>
    </StackPanel>
</Window>

3 个答案:

答案 0 :(得分:5)

正确的方法是在类上创建一个DependencyProperty来保存参数化数据,然后绑定到模板中的该属性。为了创建一个快速示例,我将使用Button.Tag属性,该属性非常适合存储像画笔一样简单的东西:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1" Height="300" Width="300">
<Page.Resources>
    <SolidColorBrush x:Key="BlackBrush" Color="Black"/>
    <SolidColorBrush x:Key="GrayBrush" Color="Gray"/>
    <Style x:Key="CustomButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border BorderBrush="{TemplateBinding Tag}" BorderThickness="3">
                        <ContentControl Content="{TemplateBinding Content}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Black Button" Tag="{StaticResource BlackBrush}"
            Style="{StaticResource CustomButtonStyle}"/>
    <Button Content="Gray Button" Tag="{StaticResource GrayBrush}"
            Style="{StaticResource CustomButtonStyle}"/>
</StackPanel>

答案 1 :(得分:4)

虽然Charlie对他的例子是正确的,但对于您的具体情况,我只使用按钮已经公开的BorderThicknessBorderBrush属性:您可以使用{TemplateBinding BorderBrush}而不是创建自己的财产。

编辑:示例xaml ...请注意我的样式默认颜色&amp;厚度,但这些可以被内联覆盖...

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="Window1" Height="300" Width="300">
<Page.Resources>
    <SolidColorBrush x:Key="BlackBrush" Color="Black"/>
    <SolidColorBrush x:Key="GrayBrush" Color="Gray"/>
    <Style x:Key="CustomButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="BorderThickness" Value="3" />
        <Setter Property="BorderBrush" Value="{StaticResource BlackBrush}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderColor="{TemplateBinding BorderThickness}">
                        <ContentControl Content="{TemplateBinding Content}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Black Button" BorderBrush="{StaticResource BlackBrush}"
            Style="{StaticResource CustomButtonStyle}"/>
    <Button Content="Gray Button" BorderBrush="{StaticResource GrayBrush}"
            Style="{StaticResource CustomButtonStyle}"/>
</StackPanel>

答案 2 :(得分:3)

看看this solution,它解决了您遇到的确切问题。