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

WPF中的参数化样式/模板?,wpf,Wpf,如果我有两个200行长的控件模板,它们只在几个字(一些颜色)上有所不同,那么如何使xaml可重用?也就是说,不必复制粘贴模板并在200行中更改3个单词 这里是一个简化的例子。这两种样式之间的唯一区别是边框颜色。那么,我可以用参数化的颜色定义一个ButtonStyle,并从中继承BlackButtonStyle和GrayButtonStyle,并在BlackButtonStyle和GrayButtonStyle中仅指定该颜色吗 下面是基于这两个答案的代码。只需在控件上设置样式,但不幸的是,

如果我有两个200行长的控件模板,它们只在几个字(一些颜色)上有所不同,那么如何使xaml可重用?也就是说,不必复制粘贴模板并在200行中更改3个单词

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


下面是基于这两个答案的代码。只需在控件上设置样式,但不幸的是,它仍然会弄乱控件的标记:

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

正确的方法通常是在可以保存参数化数据的类上创建一个
dependencProperty
,然后绑定到模板中的该属性。为了创建一个快速示例,我将使用
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>


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

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

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


看一看,它解决了您面临的确切问题。

我很难将其可视化,尽管这听起来是最好的解决方案。你能解释一下这在代码中是什么样子吗?@Berryl:看我的编辑。它和Charlie的没有太大区别,我只是使用已经存在的属性。特别要注意的是,你可以在样式中定义一个默认值,所有的按钮都会选择。是的,很酷。如果这是我的问题,我会把它作为答案!谢谢,我也这么想,但是如果我想避免使用标签,它对标准控件(即按钮)不起作用。我需要将所有按钮更改为自定义控件。此外,多次指定相同的(标记、样式)对仍然是重复的代码,但比最初的代码要少很多。您可以轻松创建一个UserControl,封装所有这些内容,并提供DependencyProperty来设置颜色。这样就不会有重复的代码。但是,您不能避免创建某种单独的实体来存储额外的数据。
<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>