WPF自定义控件(一)——Button
接触WPF也有两个多月了,有了一定的理论基础和项目经验,现在打算写一个系列,做出来一个WPF的控件库。一方面可以加强自己的水平,另一方面可以给正在学习WPF的同行一个参考。本人水平有限,难免有一些错误,望各位指出!
先上图看看各种效果:

这个Button是我继承系统Button后扩展的,主要实现了:可设置悬浮和按下时的背景,可改变形状,并可设置按钮按下后保持锁定状态等功能。
这个Button我命名为XButton,扩展的所有属性我都会以X开头命名。好了,具体的东西看代码吧!
先来Xaml的:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:KAN.WPF.XCtrl.Controls">
<Style x:Key="{x:Type ctrl:XButton}" TargetType="{x:Type ctrl:XButton}">
<Style.Resources>
<ResourceDictionary Source="/KAN.WPF.Xctrl;component/Themes/CommonStyle.xaml"/>
</Style.Resources>
<Setter Property="FocusVisualStyle" Value="{StaticResource StyleFocusVisual}"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="Silver"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ctrl:XButton}">
<!--定义视觉树-->
<Grid>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<!--这里的Path就是用来实现各种外形的-->
<Path x:Name="bdrButton"
Data="{Binding XShape, RelativeSource={RelativeSource TemplatedParent}}"
Stroke="{Binding XStrokeBrush, RelativeSource={RelativeSource TemplatedParent}}"
StrokeThickness="{Binding XStrokeThickness, RelativeSource={RelativeSource TemplatedParent}}"
Stretch="Fill" RenderTransformOrigin="0.5,0.5" Fill="{TemplateBinding Control.Background}">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Border>
<ContentPresenter Name="contentPresenter" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Focusable="False" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" Content="{TemplateBinding ContentControl.Content}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<!--设置触发器-->
<ControlTemplate.Triggers>
<!--鼠标移动上去时-->
<Trigger Property="UIElement.IsMouseOver" Value="True" >
<Setter TargetName="bdrButton" Value="{Binding XMoverBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
</Trigger>
<!--鼠标按下去时-->
<Trigger Property="ButtonBase.IsPressed" Value="True">
<Setter TargetName="bdrButton" Value="{Binding XEnterBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
</Trigger>
<!--禁用Button时-->
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="bdrButton" Value="{Binding XUnEnabledBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
</Trigger>
<!--如果设置了锁住按下的状态的属性,那么当按下时-->
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="True"/>
<Condition Property="XIsFoucedBrushLock" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter TargetName="bdrButton" Value="{Binding XEnterBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
</MultiTrigger.Setters>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
其中的StyleFocusVisual是用来定义按Tab到这个控件上的样式的,代码如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="StyleFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border Margin="0" BorderBrush="#FF9FBDF4" BorderThickness="1"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
接下来是CS的:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Imaging; namespace KAN.WPF.XCtrl.Controls
{
/// <summary>
/// 扩展按钮:可设置悬浮和按下时的背景,可改变形状,并可设置按钮按下后保持锁定状态
/// </summary>
public class XButton : Button
{
#region 依赖属性
public static readonly DependencyProperty XMoverBrushProperty;//鼠标经过时的画刷
public static readonly DependencyProperty XEnterBrushProperty;//鼠标按下时的画刷
public static readonly DependencyProperty XUnEnabledBrushProperty;//禁用时的画刷
public static readonly DependencyProperty XIsFoucedBrushLockProperty;//是否得到焦点时锁住画刷
public static readonly DependencyProperty XShapeProperty;//外形的路径
public static readonly DependencyProperty XStrokeBrushProperty;//外形的路径着色
public static readonly DependencyProperty XStrokeThicknessProperty;//外形的路径粗细(默认为0,因为有Border边框,所以要设这个值,要先把BorderThickness设为0)
#endregion #region 内部方法
/// <summary>
/// 静态构造方法
/// </summary>
static XButton()
{
//注册依赖属性
XButton.XMoverBrushProperty = DependencyProperty.Register("XMoverBrush", typeof(Brush), typeof(XButton),
new PropertyMetadata(Brushes.WhiteSmoke));
XButton.XEnterBrushProperty = DependencyProperty.Register("XEnterBrush", typeof(Brush), typeof(XButton),
new PropertyMetadata(Brushes.Silver));
XButton.XUnEnabledBrushProperty = DependencyProperty.Register("XUnEnabledBrush", typeof(Brush), typeof(XButton),
new PropertyMetadata(Brushes.Silver));
XButton.XStrokeBrushProperty = DependencyProperty.Register("XStrokeBrush", typeof(Brush), typeof(XButton),
new PropertyMetadata(Brushes.Silver));
XButton.XStrokeThicknessProperty = DependencyProperty.Register("XStrokeThickness", typeof(Double), typeof(XButton),
new PropertyMetadata(0.0));
XButton.XIsFoucedBrushLockProperty = DependencyProperty.Register("XIsFoucedBrushLock", typeof(bool), typeof(XButton),
new PropertyMetadata(false));
XButton.XShapeProperty = DependencyProperty.Register("XShape", typeof(string), typeof(XButton),
new PropertyMetadata("M 0 0 L 0 0 L 100 0 L 100 100 L 0 100 Z"));
FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(XButton), new FrameworkPropertyMetadata(typeof(XButton)));
}
#endregion #region 公布属性
/// <summary>
/// 公布属性XMoverBrush(鼠标经过时的画刷)
/// </summary>
public Brush XMoverBrush
{
get
{
return base.GetValue(XButton.XMoverBrushProperty) as Brush;
}
set
{
base.SetValue(XButton.XMoverBrushProperty, value);
}
} /// <summary>
/// 公布属性XMoverBrush(鼠标按下时的画刷)
/// </summary>
public Brush XEnterBrush
{
get
{
return base.GetValue(XButton.XEnterBrushProperty) as Brush;
}
set
{
base.SetValue(XButton.XEnterBrushProperty, value);
}
} /// <summary>
/// 公布属性XUnEnabledBrush(禁用时的画刷)
/// </summary>
public Brush XUnEnabledBrush
{
get
{
return base.GetValue(XButton.XUnEnabledBrushProperty) as Brush;
}
set
{
base.SetValue(XButton.XUnEnabledBrushProperty, value);
}
} /// <summary>
/// 公布属性XIsFoucedBrushLock(是否得到焦点时锁住画刷)
/// </summary>
public bool XIsFoucedBrushLock
{
get
{
return (bool)base.GetValue(XButton.XIsFoucedBrushLockProperty);
}
set
{
base.SetValue(XButton.XIsFoucedBrushLockProperty, value);
}
} /// <summary>
/// 公布属性XShape(外形的路径)
/// </summary>
public String XShape
{
get
{
return base.GetValue(XButton.XShapeProperty) as String;
}
set
{
base.SetValue(XButton.XShapeProperty, value);
}
} /// <summary>
/// 公布属性XStrokeBrush(外形的路径着色)
/// </summary>
public Brush XStrokeBrush
{
get
{
return base.GetValue(XButton.XStrokeBrushProperty) as Brush;
}
set
{
base.SetValue(XButton.XStrokeBrushProperty, value);
}
} /// <summary>
/// 公布属性XStrokeThickness(外形的路径粗细)
/// </summary>
public Double XStrokeThickness
{
get
{
return (Double)base.GetValue(XButton.XStrokeThicknessProperty);
}
set
{
base.SetValue(XButton.XStrokeThicknessProperty, value);
}
}
#endregion
}
}
看了代码上的注释应该都能明白吧!要是有不明白的可以留言。
至于源代码,我之后会整理几个控件后一起发上来的!
WPF自定义控件(一)——Button的更多相关文章
- WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展
一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要是对文本 ...
- WPF自定义控件与样式(2)-自定义按钮FButton
一.前言.效果图 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 还是先看看效果 ...
- WPF自定义控件与样式(15)-终结篇 & 系列文章索引 & 源码共享
系列文章目录 WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与样式(3)-TextBox & Ric ...
- WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 日历控 ...
- WPF自定义控件与样式(15)-终结篇
原文:WPF自定义控件与样式(15)-终结篇 系列文章目录 WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与 ...
- WPF自定义控件创建
WPF自定义控件创建 本文简单的介绍一下WPF自定义控件的开发. 首先,我们打开VisualStudio创建一个WPF自定义控件库,如下图: 然后,我们可以看到创建的解决方案如下: 在解决方案中,我们 ...
- WPF自定义控件(三)の扩展控件
扩展控件,顾名思义就是对已有的控件进行扩展,一般继承于已有的原生控件,不排除继承于自定义的控件,不过这样做意义不大,因为既然都自定义了,为什么不一步到位呢,有些不同的需求也可以通过此来完成,不过类似于 ...
- WPF自定义控件(二)の重写原生控件样式模板
话外篇: 要写一个圆形控件,用Clip,重写模板,去除样式引用圆形图片可以有这三种方式. 开发过程中,我们有时候用WPF原生的控件就能实现自己的需求,但是样式.风格并不能满足我们的需求,那么我们该怎么 ...
- WPF自定义控件(一)の控件分类
一.什么是控件(Controls) 控件是指对数据和方法的封装.控件可以有自己的属性和方法,其中属性是控件数据的简单访问者,方法则是控件的一些简单而可见的功能.控件创建过程包括设计.开发.调试(就是所 ...
- 【转】WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要内容: 日历控件Calendar自定义样式: 日期控件DatePicker自定 ...
随机推荐
- struts2下实现的json传递list,object。
必须的jar: java bean: package upload.progress.action; public class music { private String name; private ...
- String 去重,区分大小写
题目要求:去除,和.,相同的单词去除后面的.区分大小写 示例:输入:There is a will,there is a way. 输出There is a will there way 答案代码: ...
- qt+2012+qtcreator 配置
这个配置搞了我好久,终于搞定了,网上一大堆,总是看不懂,后来自己摸索出来的. 先贴图: 如上图:有两种配置方案: 第一:用vs2012做开发编辑.只要下载和对应插件即可,安装路径不要有空格.安装好之后 ...
- 华为OJ平台——杨辉三角的变形
import java.util.Scanner; /** * 杨辉三角的变形 *第一行为1,后面每一行的一个数是其左上角到右上角的数的和,没有的记为0 * 1 * 1 1 1 * 1 2 3 2 1 ...
- namespace的用法
C++中采用的是单一的全局变量命名空间.在这单一的空间中,如果有两个变量或函数的名字完全相同,就会出现冲突.当然,你也可以使用不同的名字,但有时我们并不知道另一个变量也使用完全相同的名字:有时为了程序 ...
- ubuntu下,apt的参数使用,很实用呦
ubuntu下apt-get 命令参数 常用的APT命令参数 apt-cache search package 搜索包 apt-cache show package 获取包的相关信息,如说明.大小.版 ...
- ios学习开发阶段小结
总结一下,开发了1个月10天的ios经验. 先晒成绩单:两个实验性质的app,一个wifi管家,一个图片壁纸软件 技术小结: 1.熟悉基本的各种ns语法:#import,#include,@class ...
- sql server命名规范
命名规范 表 表名如Order/UserAccout 符合以下规范: 1. 统一采用单数形式,反对Orders 2. 首字母大写,多个单词的话,单词首字母大写,反对order/User ...
- Symantec System Recovery
目的:备份系统,备份文件,裸机恢复,异机恢复等 工具:http://bbs.kafan.cn/thread-1800182-1-1.html 下载地址:http://pan.baidu.com/s/1 ...
- javascript之for-in循环(for-in Loops)
for-in循环应该用在非数组对象的遍历上,使用for-in进行循环也被称为“枚举”. 从技术上将,你可以使用for-in循环数组(因为JavaScript中数组也是对象),但这是不推荐的.因为如果数 ...