一、前言

程序界面上的按钮多种多样,常用的就这几种:普通按钮、图标按钮、文字按钮、图片文字混合按钮。本文章记录了不同样式类型的按钮实现方法。

二、固定样式的按钮

固定样式的按钮一般在临时使用时或程序的样式比较固定时才会使用,按钮整体样式不需要做大的改动。

2.1 普通按钮-扁平化风格

先看效果:

定义Button的样式,详见代码:

<Style x:Key="BtnInfoStyle" TargetType="Button">
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="25"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Background" Value="#43a9c7"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
<TextBlock Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="#2f96b4"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Background" Value="#2a89a4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

引用方法:

<Grid Background="White">
<StackPanel Orientation="Horizontal" Margin="10" VerticalAlignment="Top">
<Button Style="{StaticResource BtnInfoStyle}" Content="信息" Margin="5 0"/>
</Grid>

上述代码实现了Button按钮的扁平化样式,如果你想调整颜色风格,通过修改Background的值可实现默认颜色,鼠标经过颜色以及鼠标按下颜色。

2.2 图标按钮

先看效果:

Button样式的代码和扁平化Button差不多,只是把TextBlock控件替换成了Image控件,另外需要设置Button默认的背景色为透明。废话不多说看代码:

  <Style x:Key="BtnImageStyle1" TargetType="Button">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Image x:Name="Img" VerticalAlignment="Center" HorizontalAlignment="Center" Source="/Images/button1.png" Stretch="None"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Img" Property="Source" Value="/Images/button1.png"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Img" Property="Source" Value="/Images/button1.png"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

这里的button1.png需要自己准备图片资源,IsMouseOver和IsPressed的图片资源可自己替换,替换之后能有更丰富的效果呈现。

2.3 图标文字混合按钮

效果:

实现代码:

 <Style x:Key="BtnImgTxtStyle1" TargetType="Button">
<Setter Property="Foreground" Value="#555"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Image Source="Images/adshut.png" Stretch="None"/>
<TextBlock x:Name="Txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#333333" TargetName="Txt"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

2.4 文字按钮和2.3中的图标文字按钮样式差不多,只需要把Image控件去掉就行。

三、复用性高的按钮

  • 要想实现复用性高的按钮,就必须新建自定义控件。下面这个实例通过自定义控件实现上述所有效果,并且可以随意更改风格。
  • 首先在项目中右键-添加-新建项-自定义控件。

新建自定义控件之后,添加依赖属性。代码如下:

 public class ButtonEx : Button
{
static ButtonEx()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ButtonEx), new FrameworkPropertyMetadata(typeof(ButtonEx)));
} public ButtonType ButtonType
{
get { return (ButtonType)GetValue(ButtonTypeProperty); }
set { SetValue(ButtonTypeProperty, value); }
} public static readonly DependencyProperty ButtonTypeProperty =
DependencyProperty.Register("ButtonType", typeof(ButtonType), typeof(ButtonEx), new PropertyMetadata(ButtonType.Normal)); public ImageSource Icon
{
get { return (ImageSource)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
} public static readonly DependencyProperty IconProperty =
DependencyProperty.Register("Icon", typeof(ImageSource), typeof(ButtonEx), new PropertyMetadata(null)); public CornerRadius CornerRadius
{
get { return (CornerRadius)GetValue(CornerRadiusProperty); }
set { SetValue(CornerRadiusProperty, value); }
} public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(ButtonEx), new PropertyMetadata(new CornerRadius())); public Brush MouseOverForeground
{
get { return (Brush)GetValue(MouseOverForegroundProperty); }
set { SetValue(MouseOverForegroundProperty, value); }
} public static readonly DependencyProperty MouseOverForegroundProperty =
DependencyProperty.Register("MouseOverForeground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata()); public Brush MousePressedForeground
{
get { return (Brush)GetValue(MousePressedForegroundProperty); }
set { SetValue(MousePressedForegroundProperty, value); }
} public static readonly DependencyProperty MousePressedForegroundProperty =
DependencyProperty.Register("MousePressedForeground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata()); public Brush MouseOverBorderbrush
{
get { return (Brush)GetValue(MouseOverBorderbrushProperty); }
set { SetValue(MouseOverBorderbrushProperty, value); }
} public static readonly DependencyProperty MouseOverBorderbrushProperty =
DependencyProperty.Register("MouseOverBorderbrush", typeof(Brush), typeof(ButtonEx), new PropertyMetadata()); public Brush MouseOverBackground
{
get { return (Brush)GetValue(MouseOverBackgroundProperty); }
set { SetValue(MouseOverBackgroundProperty, value); }
} public static readonly DependencyProperty MouseOverBackgroundProperty =
DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata()); public Brush MousePressedBackground
{
get { return (Brush)GetValue(MousePressedBackgroundProperty); }
set { SetValue(MousePressedBackgroundProperty, value); }
} public static readonly DependencyProperty MousePressedBackgroundProperty =
DependencyProperty.Register("MousePressedBackground", typeof(Brush), typeof(ButtonEx), new PropertyMetadata());
} public enum ButtonType
{
Normal,
Icon,
Text,
IconText
}

为不同类型按钮设置样式,代码如下:

<Style TargetType="{x:Type local:ButtonEx}">
<Style.Triggers>
<Trigger Property="ButtonType" Value="Normal">
<Setter Property="Background" Value="#43a9c7"/>
<Setter Property="MouseOverBackground" Value="#2f96b4"/>
<Setter Property="MousePressedBackground" Value="#2a89a4"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="MouseOverForeground" Value="White"/>
<Setter Property="MousePressedForeground" Value="White"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ButtonEx}">
<Border x:Name="border" Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" SnapsToDevicePixels="True">
<TextBlock x:Name="txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Background" Value="{Binding MouseOverBackground,RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="txt" Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="border" Property="BorderBrush" Value="{Binding MouseOverBorderbrush,RelativeSource={RelativeSource TemplatedParent}}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="border" Property="Background" Value="{Binding MousePressedBackground,RelativeSource={RelativeSource TemplatedParent}}"/>
<Setter TargetName="txt" Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}"/> </Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ButtonType" Value="Icon">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ButtonEx}">
<Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Image x:Name="Img" VerticalAlignment="Center" HorizontalAlignment="Center" Source="{TemplateBinding Icon}" Stretch="None"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="0.8"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.9"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ButtonType" Value="Text">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="#002c99"/>
<Setter Property="MouseOverForeground" Value="#FF2c99"/>
<Setter Property="MousePressedForeground" Value="#002c99"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ButtonEx}">
<TextBlock x:Name="txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="txt"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="txt"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ButtonType" Value="IconText">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Foreground" Value="#555"/>
<Setter Property="MouseOverForeground" Value="#555"/>
<Setter Property="MousePressedForeground" Value="#555"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ButtonEx}">
<Border>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Image Source="{TemplateBinding Icon}" Stretch="None"/>
<TextBlock x:Name="Txt" Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{Binding MouseOverForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="Txt"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="{Binding MousePressedForeground,RelativeSource={RelativeSource TemplatedParent}}" TargetName="Txt"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers> </Style>

然后就可以引用该控件了:

 <Grid>
<WrapPanel>
<local:ButtonEx Content="信息" Width="75" Height="25" Margin="10" ButtonType="Normal"/>
<local:ButtonEx Icon="/Images/button1.png" Margin="10" ButtonType="Icon"/>
<local:ButtonEx Content="文字按钮" Margin="10" ButtonType="Text"/>
<local:ButtonEx Content="图文按钮" Icon="/Images/adshut.png" Margin="10" ButtonType="IconText"/>
</WrapPanel>
</Grid>

效果如下:

至此已经完成Button控件的扩展功能,如果想要添加动画或者设置图标的位置和边距等,可以自己另外添加依赖属性来扩展。

所有代码已经上传到github:https://github.com/caomfan/WpfDemo.git

WPF自定义控件与样式-自定义按钮(Button)的更多相关文章

  1. WPF自定义控件与样式(2)-自定义按钮FButton

    一.前言.效果图 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 还是先看看效果 ...

  2. 【转】WPF自定义控件与样式(2)-自定义按钮FButton

    一.前言.效果图 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等 还是先看看效果图吧:   定义Button按钮名称叫FButton,主要是集成了 ...

  3. WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 日历控 ...

  4. 【转】WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要内容: 日历控件Calendar自定义样式: 日期控件DatePicker自定 ...

  5. WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Che ...

  6. WPF自定义控件与样式(6)-ScrollViewer与ListBox自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Scr ...

  7. WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Dat ...

  8. WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...

  9. WPF自定义控件与样式(10)-进度控件ProcessBar自定义样

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Pro ...

随机推荐

  1. 大三小学期 Android开发的一些经验

    1.同一个TextView几种颜色的设置: build=(TextView)findViewById(R.id.building); SpannableStringBuilder style = ne ...

  2. html备战春招の一

    html不是一种编程语言,而是一种标记语言,通过使用标签来标记网页. 对于中文网页需要使用 <meta charset="utf-8"> 声明编码,否则会出现乱码.有些 ...

  3. 对于最近线上服务以及京东等大型互联网公司对java工程师要求的一些思考

    当下线上服务为了减少上线,经常搞成配置化,配置化对于版本以及持续集成本身是很大破坏,对于此,我个人持保留态度, 是反对过多东西进行配置化,其实配置化本身没有什么问题,关键是动态对配置进行修改而没有与代 ...

  4. vue v-for输出表格结构

    v-for输出表格结构 数据库结构如下: 原理: 两个数组 a, b,  数组a的值,是数组b的键(索引), 变量拼接(红色区域): <table> <tr> <th v ...

  5. Django数据模型——通用字段选项

    字段 一个模型最重要也是唯一必需的部分,是它定义的数据库字段 字段名称限制 1.字段名不能是python保留字,这样会导致python语法错误 2.字段不能包含连续一个以上的下划线,这样会和Djang ...

  6. Spring Boot应用的后台运行配置

    酱油一篇,整理一下关于Spring Boot后台运行的一些配置方式.在介绍后台运行配置之前,我们先回顾一下Spring Boot应用的几种运行方式: 运行Spring Boot的应用主类 使用Mave ...

  7. 【眼见为实】自己动手实践理解REPEATABLE READ && Next-Key Lock

    首先设置数据库隔离级别为可重复读(REPEATABLE READ): set global transaction isolation level REPEATABLE READ ; set sess ...

  8. Entity Framework——并发策略

    使用EF框架遇到并发时,一般采取乐观并发控制. 1支持并发检验 为支持并发检验,需要对实体进行额外的设置.默认情况下是不支持并发检验的.有以下两种方式: 方式名称 说明 时间戳注解/行版本 使用Tim ...

  9. [BZOJ 4417][Shoi2013]超级跳马

    4417: [Shoi2013]超级跳马 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 379  Solved: 230[Submit][Status ...

  10. 自定义ArrayList

    自定义实现ArrayList很简单,只需要明白下面几点 1.ArrayList 底层是由数组组成的 2.数组有容量限制,但是ArrayList并没有(实际上也有,Integer.MAX_VALUE). ...