一、前言

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

二、固定样式的按钮

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

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. [C#].Net Core下全局自定义身份过滤器使用AllowAnonymous属性

    假设一种情况:项目中需要做认证和权限控制,而且需要权限才能访问的控制器要远多于可以匿名访问的(类似AO系统那样,登陆了才能用). 那在每个控制器上加一个 [Authorize] 是能解决问题,反正正我 ...

  2. 安装Accumulo——突破自己,就是成长

    前言 在我刚开始接触分布式集群的时候,是自己在几台虚拟机中手动安装的 Hadoop 和 Spark ,所以当时对 Hadoop 的配置有个简单的印象 ,但是后面发现了 Cloudera 和 Ambar ...

  3. python import自定义模块方法

    转自:http://www.cnitblog.com/seeyeah/archive/2009/03/15/55440.html python包含子目录中的模块方法比较简单,关键是能够在sys.pat ...

  4. Learn Plan

    2018-02-05 1.正则表达式的熟悉和使用 2.Spring-boot 框架的使用 3.React的如何和使用 4.英语的单词发音的纠正和词汇的记忆. 5.github 命令行的使用 6.jav ...

  5. [POJ1631] nlogn求LIS

    用到了algorithm自带的lower_bound函数进行二分查找 #include<cstdio> #include<cstring> #include<algori ...

  6. poj 2503 查字典

    Description You have just moved from Waterloo to a big city. The people here speak an incomprehensib ...

  7. Jmeter4.0----安装教程(2)

    1.检查安装环境 1.1 JDK要求 JDK版本:1.6 + 1.2 检查是否安装JDK win + R 快捷键打开运行,输入 cmd 打开面板,在面板中输入 java -version,出现如下信息 ...

  8. Redis --> Ubuntu安装redis

    Ubuntu安装redis   一.下载安装 root@21ebdf03a086:/# apt-cache search redis root@21ebdf03a086:/# apt-get inst ...

  9. 打印十字图 JAVA 递归实现

    这个是我自己想的,头疼了一个下午,不过还好.做出来了.在网上找这道题但没有找到用递归的做法. /*递归思想实现 * 标题:打印十字图 小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示(可 ...

  10. struct2_拦截器知识点.

    Struts2拦截器原理: Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个 ...