更改样式控件中的控件模板的一部分?

Change part of controltemplate in styled controls?

我已经使用 ControlTemplate 自定义了 ToggleButton 控件,如下所示:

<StackPanel>
    <StackPanel.Resources>
        <Style x:Key="OptionBarButton" TargetType="{x:Type ToggleButton}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ToggleButton">
                        <Border Padding="18,12,18,12" Background="{TemplateBinding Background}">
                            <ContentPresenter />
                        </Border>
                        <ControlTemplate.Triggers>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsChecked" Value="True" />
                                    <Condition Property="IsMouseOver" Value="True" />
                                </MultiTrigger.Conditions>
                                <MultiTrigger.Setters>
                                    <Setter Property="Background" Value="DarkBlue" />
                                </MultiTrigger.Setters>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsChecked" Value="True" />
                                    <Condition Property="IsMouseOver" Value="False" />
                                </MultiTrigger.Conditions>
                                <MultiTrigger.Setters>
                                    <Setter Property="Background" Value="SkyBlue" />
                                </MultiTrigger.Setters>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsChecked" Value="False" />
                                    <Condition Property="IsMouseOver" Value="False" />
                                </MultiTrigger.Conditions>
                                <MultiTrigger.Setters>
                                    <Setter Property="Background" Value="#88000000" />
                                </MultiTrigger.Setters>
                            </MultiTrigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="IsChecked" Value="False" />
                                    <Condition Property="IsMouseOver" Value="True" />
                                </MultiTrigger.Conditions>
                                <MultiTrigger.Setters>
                                    <Setter Property="Background" Value="#F0000000" />
                                </MultiTrigger.Setters>
                            </MultiTrigger>
                        </ControlTemplate.Triggers>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </StackPanel.Resources>

    <ToggleButton Style="{StaticResource OptionBarButton}">
        <Image Source="../Assets/icons/action.png" Height="26" RenderOptions.BitmapScalingMode="Fant" />
    </ToggleButton>

    <ToggleButton Style="{StaticResource OptionBarButton}">
        <Image Source="../Assets/icons/action2.png" Height="26" RenderOptions.BitmapScalingMode="Fant" />
    </ToggleButton>

</StackPanel>

这很好用,但是我现在想更改某些样式控件中模板的某些部分,即 IsChecked 颜色状态 (SkyBlue/DarkBlue)。

是否可以在使用模板时修改/传递这些颜色in/to模板?我知道我可以使用附加属性 or/and subclass ToggleButton class (向其添加依赖属性),但我想知道是否有更惯用的方法来解决这个问题,也许只有 xaml。对于这样一个简单的用例,必须在 C# 中编写自定义代码似乎有点矫枉过正?

不幸的是,ControlTemplates 是一个孤注一掷的东西。如果您想更改您在其中引用的颜色,则必须切换模板。我认为在模板中 引用资源 不适合您。

我将为 OptionBarButton 中的每种可变颜色创建依赖属性。

据我所知,如果没有代码,没有简单的方法可以做到这一点,但如果您真的想要 - 您可以以某种方式利用动态资源。通常动态资源用于在运行时更改所有控件实例的外观。您从模板中引用动态资源,然后更改该资源,所有控件都会反映此更改。在这种情况下,这可能不是您所需要的,因为您想要更改 "some parts of the template in some of the styled controls"。您仍然可以这样做:

<!-- default checked and over color -->
<SolidColorBrush x:Key="TgCheckedAndOver" Color="DarkBlue" />
<!-- default checked color -->
<SolidColorBrush x:Key="TgChecked" Color="SkyBlue" />
<Style 
       TargetType="{x:Type ToggleButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ToggleButton">
                <Border Padding="18,12,18,12"
                        Background="{TemplateBinding Background}">
                    <ContentPresenter />
                </Border>
                <ControlTemplate.Triggers>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsChecked"
                                       Value="True" />
                            <Condition Property="IsMouseOver"
                                       Value="True" />
                        </MultiTrigger.Conditions>
                        <MultiTrigger.Setters>
                            <Setter Property="Background"
                                    Value="{DynamicResource TgCheckedAndOver}" />
                        </MultiTrigger.Setters>
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsChecked"
                                       Value="True" />
                            <Condition Property="IsMouseOver"
                                       Value="False" />
                        </MultiTrigger.Conditions>
                        <MultiTrigger.Setters>
                            <Setter Property="Background"
                                    Value="{DynamicResource TgChecked}" />
                        </MultiTrigger.Setters>
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsChecked"
                                       Value="False" />
                            <Condition Property="IsMouseOver"
                                       Value="False" />
                        </MultiTrigger.Conditions>
                        <MultiTrigger.Setters>
                            <Setter Property="Background"
                                    Value="#88000000" />
                        </MultiTrigger.Setters>
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsChecked"
                                       Value="False" />
                            <Condition Property="IsMouseOver"
                                       Value="True" />
                        </MultiTrigger.Conditions>
                        <MultiTrigger.Setters>
                            <Setter Property="Background"
                                    Value="#F0000000" />
                        </MultiTrigger.Setters>
                    </MultiTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这是动态资源的常规使用。现在,当您只想为特定控件更改外观时,您可以这样做:

<ToggleButton>
    <ToggleButton.Resources>
        <!-- override default resources -->
        <SolidColorBrush x:Key="TgChecked" Color="Yellow" />
        <SolidColorBrush x:Key="TgCheckedAndOver"
                         Color="Green" />
    </ToggleButton.Resources>
    <Image Source="../Assets/icons/action.png" Height="26" RenderOptions.BitmapScalingMode="Fant" />
</ToggleButton>

因为您将具有相同键 "closer" 的新资源放置到控件中 - 模板将使用它们而不是默认的,并且只有这个特定的控件会这样做,而不是所有的。