【问题标题】:Is it possible to extend a ControlTemplate the same way you extend a Style in WPF?是否可以像在 WPF 中扩展 Style 一样扩展 ControlTemplate?
【发布时间】:2009-10-09 20:17:40
【问题描述】:

所以问题是我有一个主 ControlTemplate,它定义了我们正在设计的新按钮外观的最基本内容。但我想为这个按钮做 3 个其他控制模板,这样我们就可以在其中设置不同的颜色;但我不想复制粘贴主 ControlTemplate 并在那里更改颜色,而是想从中“继承”(如 Style 中的 BasedOn 属性)并更改继承的 ControlTemplate 中的颜色。

这可能吗?

谢谢!

【问题讨论】:

    标签: wpf controltemplate


    【解决方案1】:

    找到了解决方案。您不扩展 ControlTemplates,而是定义您想要的所有基本行为,然后让样式或控件本身修改它。以下面的例子为例。 ControlTemplate 为我的矩形设置 OpacityMask 和圆角,Styles 设置每个按钮的背景颜色(借助 TemplateBinding),这就是我的解决方案:

        <Window.Resources>
            <ControlTemplate x:Key="BaseMainButtonTemplate" TargetType="{x:Type Button}">
                <Grid TextBlock.Foreground="White" TextBlock.FontFamily="Calibri">
                    <Rectangle Stroke="#FFE8E6E6" x:Name="rectangle" RadiusX="14.5" RadiusY="14.5" Fill="{TemplateBinding Property=Background}"> <!-- This TemplateBinding takes the color set by the style and applies it to the rectangle. Doing it this way, allows the style to modify the background color -->
                        <Rectangle.OpacityMask>
                            <LinearGradientBrush EndPoint="0,1" SpreadMethod="Reflect">
                                <GradientStop Offset="0" Color="Transparent"></GradientStop>
                                <GradientStop Offset="1" Color="Gray"></GradientStop>
                            </LinearGradientBrush>
                        </Rectangle.OpacityMask>
                    </Rectangle>
                    <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <!-- OpacityMask when it's Focused, Defaulted and Mouse is over -->
                    <Trigger Property="IsFocused" Value="True"/>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="OpacityMask" TargetName="rectangle">
                            <Setter.Value>
                                <LinearGradientBrush EndPoint="0,1" SpreadMethod="Repeat">
                                    <GradientStop Offset="1" Color="Transparent"></GradientStop>
                                    <GradientStop Offset="0" Color="Gray"></GradientStop>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                    <!-- OpacityMask when it's pressed -->
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Stroke" TargetName="rectangle">
                            <Setter.Value>
                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                    <GradientStop Color="#FF223472" Offset="0"/>
                                    <GradientStop Color="#FFF2F0F0" Offset="0.911"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="StrokeThickness" TargetName="rectangle" Value="3"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
            <Style x:Key="BlueButtonStyle" TargetType="{x:Type Button}">
                <Setter Property="Background" Value="Blue" />
                <Setter Property="Template" Value="{StaticResource BaseMainButtonTemplate}">
                </Setter>
            </Style>
            <Style x:Key="RedButtonStyle" TargetType="{x:Type Button}">
                <Setter Property="Background" Value="Red" />
                <Setter Property="Template" Value="{StaticResource BaseMainButtonTemplate}">
                </Setter>
            </Style>
            <Style x:Key="GreenButtonStyle" TargetType="{x:Type Button}">
                <Setter Property="Background" Value="Green" />
                <Setter Property="Template" Value="{StaticResource BaseMainButtonTemplate}">
                </Setter>
            </Style>
        </Window.Resources>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <StackPanel>
                <Button Style="{StaticResource BlueButtonStyle}" Height="30" Content="Test">
                </Button>
                <Button Style="{StaticResource RedButtonStyle}" Height="30" Content="Test">
                </Button>
                <Button Style="{StaticResource GreenButtonStyle}" Height="30" Content="Test">
                </Button>
            </StackPanel>
        </Grid>
    

    【讨论】:

    • 是的,这是最好的方法。松散地说,ControlTemplate 应该定义那里的内容,Style 修改 ControlTemplate 上的属性以定义它的实际外观。
    • 如果你的控件模板中有你的控件没有的属性,这不起作用。
    【解决方案2】:

    或者,您可以在控制模板中定义对任何依赖项属性的“DynamicResource”引用,并在存在可用资源的情况下让它解析它的值。 例如,您可以设置 Background="{DynamicResource SomeBrushColorVariable}" 然后 SomeBrushColorVariable 可以根据不同的 ResourceDictionaries 进行更改,这些 ResourceDictionaries 合并到您的 App.xaml 文件中,甚至由用户根据某些用户首选项显示设置或配色方案进行设置。

    【讨论】:

      猜你喜欢
      • 2011-04-28
      • 2013-06-14
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-17
      • 2020-12-22
      • 2018-08-16
      相关资源
      最近更新 更多