如何在 WPF 中基于另一个按钮样式构建按钮样式

How to build a button style based on another in WPF

我是 WPF 新手,通过快速教程,我成功获得了如下所示的个性化按钮样式:

<Style x:Key="ButtonFocusVisual">
    <Setter Property="Control.Template">
        <Setter.Value>
            <ControlTemplate>
                <Border>
                    <Rectangle Margin="2" StrokeThickness="1" Stroke="#60000000" StrokeDashArray="1 2"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<SolidColorBrush x:Key="NormalBrush" Color="#FF0C0C13"/>
<SolidColorBrush x:Key="LightBrush" Color="#FF2E2E3E"/>
<SolidColorBrush x:Key="PressedBrush" Color="#FF209FD4"/>

<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#FF494968" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#FF2E2E3E" />

<SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />
<SolidColorBrush x:Key="HorizontalNormalBrush" Color="AntiqueWhite"/>
<SolidColorBrush x:Key="HorizontalLightBrush" Color="AntiqueWhite"/>
<SolidColorBrush x:Key="DarkBrush" Color="AntiqueWhite"/>

<SolidColorBrush x:Key="NormalBorderBrush" Color="Aqua"/>
<Style x:Key="MyButtonStyle" TargetType="Button">
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="OverridesDefaultStyle" Value="true"/>
    <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border x:Name="Border"  BorderThickness="1" Background="{StaticResource NormalBrush}" BorderBrush="#FF2E2E3E">
                    <ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True"/>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter TargetName="Border" Property="Background" Value="{StaticResource LightBrush}" />
                    </Trigger>
                    <Trigger Property="IsPressed" Value="true">
                        <Setter TargetName="Border" Property="Background" Value="{StaticResource PressedBrush}" />
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" />
                        <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

看来我们确实需要重写 ControlTemplate 并且为了保留一些功能(例如悬停鼠标时的行为)我们需要定义它们。在这里对我来说已经很奇怪的是,在 ControlTemplate 下定义了一个 Border 标签,然后触发器引用那个 Border。所以作为第一个问题,为什么 Border 而不是别的?

但现在的主要问题是:假设我想要完全相同的按钮,具有相同的颜色和功能,但没有边框。我尝试使用类似于以下内容的 BasedOn:

<Style x:Key="MyButtonStyleNoBorder" TargetType="{x:Type Button}"  BasedOn="{StaticResource MyButtonStyle}">
    <Setter Property="BorderThickness" Value="0"/>
</Style>

但没办法。我找到的唯一解决方案是复制 MyButtonStyle 的整个代码,然后仅将一个字符 (!) 更改为 BorderThickness="0"。但这对我来说看起来很愚蠢。你能帮忙吗?

So as a first question, why Border and not something else?

名为 Border 的元素是最外层元素,其子元素将继承其大部分状态,在本例中为背景。

But now the main question is: suppose I want exactly the same button, with the same colors and functionalities but without the borders.

如果您喜欢没有边框的按钮,您可以直接将按钮的 BorderThickness 属性 设置为 0,或者在样式中设置为 setter。

The only solution I found is to copy the entire code of MyButtonStyle and then to change only one character (!) to have BorderThickness="0". But this to me looks stupid. Can you please help?

样式是一种 属性 要在目标上更改的列表。 basedOn 功能将使用 basedOn 样式和 "add" 来自新样式的新 setter。

模板更像是控件的绘图(和一些图形行为),当您指定一个新模板时,您只需丢弃旧模板。我可以在那里做一个 basedOn。我们如何确定使用什么和替换什么?

不是您想要的答案,但希望您能得到它。


<Border x:Name="Border"  BorderThickness="{TemplateBinding BorderThickness}" Background="{StaticResource NormalBrush}" BorderBrush="#FF2E2E3E">
                <ContentPresenter Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="True"/>
            </Border>

将获取 Button 对象在 BorderThickness 上获得的值。

我会使用 MVVM 完成此操作(如果您还没有考虑 MVVM)。 在绑定到按钮的 ViewModel 中,我会添加一个 属性 "IsBorderLess".

然后,在触发器上:

<ControlTemplate.Triggers>
      <DataTrigger Binding="{Binding IsBorderLess}" Value="True">
           <Setter TargetName="Border" Property="BorderThickness" Value="0"/>
      </DataTrigger>
      <DataTrigger Binding="{Binding IsBorderLess}" Value="False">
           <Setter TargetName="Border" Property="BorderThickness" Value="10"/>
      </DataTrigger>
   ..........