如何更改 属性 模板中基于另一个样式的控件模板的 属性

How to change the property of a controltemplate within the property template for a Style basedon another

我正在尝试为项目设置自定义样式,同时维护隐式 UWP 样式并维护大量隐式 UWP 样式属性。

在这个例子中,我想保留所有默认的 UWP 按钮样式并设置一个键来引用。这使我可以根据此默认设置自定义样式

带键 DefaultButtonStyle 的默认 UWP 样式

<Style TargetType="Button" x:Key="DefaultButtonStyle">
        <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}" />
        <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
        <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundTransparentBrush}" />
        <Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
        <Setter Property="Padding" Value="8,4,8,4" />
        <Setter Property="HorizontalAlignment" Value="Left" />
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
        <Setter Property="FontWeight" Value="Normal" />
        <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
        <Setter Property="UseSystemFocusVisuals" Value="True" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal">
                                    <Storyboard>
                                        <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="PointerOver">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPointerOver}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPointerOver}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPointerOver}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                        </Storyboard>
                                    </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPressed}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPressed}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPressed}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <PointerDownThemeAnimation Storyboard.TargetName="RootGrid"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundDisabled}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushDisabled}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundDisabled}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ContentPresenter x:Name="ContentPresenter"
                                          BorderBrush="{TemplateBinding BorderBrush}"
                                          BorderThickness="{TemplateBinding BorderThickness}"
                                          Content="{TemplateBinding Content}"
                                          ContentTransitions="{TemplateBinding ContentTransitions}"
                                          ContentTemplate="{TemplateBinding ContentTemplate}"
                                          Padding="{TemplateBinding Padding}"
                                          HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                          AutomationProperties.AccessibilityView="Raw"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

然后我想基于此样式创建自定义样式,并且只更改必要的属性(这使我可以非常轻松地跟踪我正在更改的属性)

我的自定义样式基于 DefaultButtonStyle

        <Style TargetType="Button" x:Key="CustomButtonStyle" BasedOn="{StaticResource DefaultButtonStyle}">
        <Setter Property="Padding" Value="3,3,3,3"/>
        <Setter Property="FocusVisualMargin" Value="-3"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid CornerRadius="15">
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

我的问题是我想在模板 属性 中更改控件模板的属性。但是,如您所料,在上面的代码中,当我尝试将网格的 CornerRadius 设置为 15 时,这是我的 ControlTemplate 的唯一 属性(即保留默认样式属性的 none ).

我猜测我可能需要在某处为我的控件模板或网格提供另一个关键参考。我最好不要完整地复制和粘贴 controltemple,因为以这种方式设置它的目的是使我正在更改的属性非常明显。

非常感谢任何帮助。

谢谢,

My issue is that I want to change properties for the control template within the template property.

当您在 CustomButtonStyle 中设置 Template 属性 时,它将被覆盖。而且我不知道你为什么要根据默认按钮样式新建一个CustomButtonStyle,你可以直接使用默认样式并修改RootGrid CornerRadius 属性。

要添加 CornerRadius 属性,您可以为您的按钮添加新的依赖项 属性,然后将 CornerRadius 绑定到 RootGrid 带有 TemplateBinding 标记。

<Grid x:Name="RootGrid" Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding MyCornerRadius}">

代码隐藏

public sealed class MyCustomButton : Button
{
    public MyCustomButton()
    {
        this.DefaultStyleKey = typeof(MyCustomButton);
    }
    public CornerRadius MyCornerRadius
    {
        get { return (CornerRadius)GetValue(MyCornerRadiusProperty); }
        set { SetValue(MyCornerRadiusProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyCornerRadius.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyCornerRadiusProperty =
        DependencyProperty.Register("MyCornerRadius", typeof(CornerRadius), typeof(MyCustomButton), new PropertyMetadata(0));

}

用法

<local:MyCustomButton  Content="Hello" MyCornerRadius="15"/>

更多可以参考Custom dependency properties.