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自定 ...
随机推荐
- 笔记本win7制作wifi
笔记本win7系统, 要打开笔记本无线网卡 1. 运行 netsh wlan set hostednetwork mode=allow ssid=testwifi key=testpass model ...
- git 仓库操作
一.git 仓库从远程clone 首先要建立一个本地空目录文件比如 RuntimeJsonModel,然后: 1. git init 2. git clone https://github.com/G ...
- CSS 宝库
Cascading Style Sheets, 层叠样式表单或者层叠样式表.简称CSS. 目的是为了表现HTML或者XML的样式. 可以做到网页内容和表现的分离.可以说,CSS是一种表现语言. h5禁 ...
- Linux选型:开源不是免费 首选红帽和SUSE
首发:http://tech.it168.com/a2014/0324/1606/000001606245.shtml 企业级服务器系统选型报告:http://www.it168.com/redian ...
- [drp 6]接口和抽象类的区别,及其应用场景
导读:在很多时候,接口和抽象类可以替换.发现这个问题,还是之前学习设计模式的时候,看到那个UML图发现的.那么,究竟在什么时候使用接口,什么时候使用抽象类呢?现在结合这个项目,做一个总结. 一.接口 ...
- CSS常用的属性命名
页头:header 如:#header{属性:属性值;}或.header{属性:属性值;},也许你需要了解class与id区别及用法 登录条:loginBar 标志:logo ...
- Loadrunner:POP3协议录制收信,使用foxmail录制到的脚本为空
以下录制方法使得录制到的脚本为空: (1)打开Virtual User Generator,点击“新建Vuser脚本”,在弹出的向导页面,选择“新建单协议脚本”,选择“POP3”协议,并确定 (2)在 ...
- Android Malware Analysis
A friend of mine asked me help him to examine his Android 5.0 smartphone. He did not say what's wron ...
- Oracle多线程并行使用、关联与指定索引执行
nologging AS SELECT /*+parallel(4) leading(s a) use_hash(A) index(s IDX_CS_SERVICE_RECORD_MD2_04) */ ...
- Android IOS WebRTC 音视频开发总结(七)-- 基于浏览器的开发
前面写的一系列总结都是讲webrtc如何下载,编译,开发的,有些人可能有点云里雾里了,WEBRTC不是用来搞跨浏览器开发的吗,怎么我讲的这些跟浏览器扯不上任何关系,其实看看下面这个架构图,你就明白了, ...