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自定 ...
随机推荐
- java解析xml的4种经典方法
========================================== xml文件 <?xml version="1.0" encoding="GB2 ...
- IIS7.0设置404错误页,返回500状态码
一般在II6下,设置自定义404错误页时,只需要在错误页中选择自定义的页面,做自己的404页面即可.但是在IIS7.0及以上时,设置完404错误页后,会发现状态码返回的是500,并且可能会引起页面乱码 ...
- (转)C#进行图像处理的几种方法(Bitmap,BitmapData,IntPtr)
转自 http://blog.sina.com.cn/s/blog_628821950100wh9w.html C#进行图像处理的几种方法 本文讨论了C#图像处理中Bitmap类.BitmapData ...
- 解决visual studio已安装的问题
使用Windows Install Clean Up(用管理员身份打开),找到相应的软件
- oracle 清除当前用户的回收站
--清除当前用户的回收站:purge recyclebin; --删除表数据truncate table --查看当前用户回收站select * from user_recyclebin t;
- KMP算法模板
不懂的话推荐看这篇博客,讲的很清楚 http://blog.csdn.net/v_july_v/article/details/7041827 #include<iostream> #in ...
- Android开发如何去除标题栏title
虽然是一个小问题,今天遇到了,也就写下来吧.防止自己忘掉. 取消标题栏的方式有两种,一种是在代码添加,另一种是在AndroidManifest.xml里面添加. 1.在代码中实现:在此方法setCon ...
- ASP.NET 数据库页面访问简单工具
在工作中,有很多项目已上线后,很多项目的数据库服务器都不会对外开放的,外网想直接访问客户数据库服务器时,可能会出现困难. 这时就需要一个可以查询,更新数据库操作的页面了: 本来用sql语句直接操作数据 ...
- Mongodb解决不能连接到服务器的错误
注:这次解决的这个问题的前提是之前打开MongoDB之后,再次使用的时候无法连接了(使用mongod和mongo都不对) 闲话:遇到这种问题真是让人恼火,所以说句sun of beach,好了~爽 正 ...
- js跳转页面方法(转)
<span id="tiao">3</span><a href="javascript:countDown"></a& ...