如何在 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>
..........
我是 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>
..........