WPF自定义控件与样式-自定义按钮(Button)
一、前言
程序界面上的按钮多种多样,常用的就这几种:普通按钮、图标按钮、文字按钮、图片文字混合按钮。本文章记录了不同样式类型的按钮实现方法。
二、固定样式的按钮
固定样式的按钮一般在临时使用时或程序的样式比较固定时才会使用,按钮整体样式不需要做大的改动。
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)的更多相关文章
- WPF自定义控件与样式(2)-自定义按钮FButton
一.前言.效果图 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 还是先看看效果 ...
- 【转】WPF自定义控件与样式(2)-自定义按钮FButton
一.前言.效果图 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等 还是先看看效果图吧: 定义Button按钮名称叫FButton,主要是集成了 ...
- WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 日历控 ...
- 【转】WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要内容: 日历控件Calendar自定义样式: 日期控件DatePicker自定 ...
- WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Che ...
- WPF自定义控件与样式(6)-ScrollViewer与ListBox自定义样式
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Scr ...
- WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Dat ...
- WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...
- WPF自定义控件与样式(10)-进度控件ProcessBar自定义样
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Pro ...
随机推荐
- 今年暑假不AC【贪心】
Problem Description "今年暑假不AC?""是的.""那你干什么呢?""看世界杯呀,笨蛋!"" ...
- fitnesse - 安装部署
fitnesse - 安装部署 2017-09-29 1 先决条件Java环境 确保机器上装了java, java -version 2 安装fitnesse http://fitnesse.org/ ...
- [转]What is a WebRTC Gateway anyway? (Lorenzo Miniero)
[转]What is a WebRTC Gateway anyway? (Lorenzo Miniero) https://webrtchacks.com/webrtc-gw/ As I mentio ...
- java线程学习第一天__低配版的卖面包机
package Thread;import javax.xml.bind.ValidationEvent;class snacks{ private int SaledSnacks=0; ...
- 发个2012年用java写的一个控制台小游戏
时间是把杀狗刀 突然发现了12年用java写的控制台玩的一个文字游戏,有兴趣的可以下载试试哈汪~ 里面难点当时确实遇到过,在计算倒计时的时候用了多线程,当时还写了好久才搞定.很怀念那个时间虽然不会做游 ...
- [.Net Core] 在 Mvc 中简单使用日志组件
在 Mvc 中简单使用日志组件 基于 .Net Core 2.0,本文只是蜻蜓点水,并非深入浅出. 目录 使用内置的日志组件 简单过渡到第三方组件 - NLog 使用内置的日志 下面使用控制器 Hom ...
- nginx的自动化安装和启停脚本
个人原创,转载请注明出处和作者,否则依法追究法律责任 author: headsen chen date: 2018-03-07 14:39:11 nginx_install.sh #!/bin/ ...
- Python基础-week04
本节内容摘要:#Author:http://www.cnblogs.com/Jame-mei 装饰器 迭代器&生成器 Json & pickle 数据序列化 软件目录结构规范 作业:A ...
- CCF-CSP 201709-4通信网络
问题描述 某国的军队由N个部门组成,为了提高安全性,部门之间建立了M条通路,每条通路只能单向传递信息,即一条从部门a到部门b的通路只能由a向b传递信息.信息可以通过中转的方式进行传递,即如果a能将信息 ...
- Android GC Log
最近在研究Android内存垃圾回收的内容,遇到一些自己之前不知道的技巧和方法.现在分享一种简单的在Logcat中可以看到垃圾回收状态的方法.经常关注Logcat日志的童鞋偶尔会看到一条类似于以下形式 ...