接触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的更多相关文章

  1. WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式、水印、Label标签、功能扩展

    一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要是对文本 ...

  2. WPF自定义控件与样式(2)-自定义按钮FButton

    一.前言.效果图 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 还是先看看效果 ...

  3. WPF自定义控件与样式(15)-终结篇 & 系列文章索引 & 源码共享

    系列文章目录  WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与样式(3)-TextBox & Ric ...

  4. WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 日历控 ...

  5. WPF自定义控件与样式(15)-终结篇

    原文:WPF自定义控件与样式(15)-终结篇 系列文章目录  WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与 ...

  6. WPF自定义控件创建

    WPF自定义控件创建 本文简单的介绍一下WPF自定义控件的开发. 首先,我们打开VisualStudio创建一个WPF自定义控件库,如下图: 然后,我们可以看到创建的解决方案如下: 在解决方案中,我们 ...

  7. WPF自定义控件(三)の扩展控件

    扩展控件,顾名思义就是对已有的控件进行扩展,一般继承于已有的原生控件,不排除继承于自定义的控件,不过这样做意义不大,因为既然都自定义了,为什么不一步到位呢,有些不同的需求也可以通过此来完成,不过类似于 ...

  8. WPF自定义控件(二)の重写原生控件样式模板

    话外篇: 要写一个圆形控件,用Clip,重写模板,去除样式引用圆形图片可以有这三种方式. 开发过程中,我们有时候用WPF原生的控件就能实现自己的需求,但是样式.风格并不能满足我们的需求,那么我们该怎么 ...

  9. WPF自定义控件(一)の控件分类

    一.什么是控件(Controls) 控件是指对数据和方法的封装.控件可以有自己的属性和方法,其中属性是控件数据的简单访问者,方法则是控件的一些简单而可见的功能.控件创建过程包括设计.开发.调试(就是所 ...

  10. 【转】WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要内容: 日历控件Calendar自定义样式: 日期控件DatePicker自定 ...

随机推荐

  1. mysql命令整理0919 不定期更新中

    1)新建数据库 create database +database_name:         查询数据库  show databases;       切换数据库   use database_na ...

  2. JDK源码分析之集合03LinkedList

    一.前言 LinkedList是双向列表,实现方式是使用链表的方式保存元素:除了第一个和最后一个元素外,每一个节点都包含一个指向前一个和指向后一个节点的指针和元素的值.其特点是插入删除效率高,而随机访 ...

  3. 使用AS3.0代码实现给图片添加滤镜的模糊与斜角效果

    滤镜可应用于任何显示对象(即,从 DisplayObject 类继承的对象), 例如 MovieClip.SimpleButton.TextField 和 Video 对象,以及 BitmapData ...

  4. 【LeetCode】18. 4Sum

    题目: 思路:这题和15题很像,外层再加一个循环稍作修改即可 public class Solution { public List<List<Integer>> fourSu ...

  5. express 框架初步体验

    一. 安装express 1.打开cmd  全局安装express 输入:npm install -gd express 2. 安装命令行工具,不然你输入express 会出现 不是内部命令. 输入: ...

  6. VBS创建数据表

    '创建数据表'参数:strDBPath 字符串型 数据库路径'参数:strTableName 字符串型 需要创建的数据表的名称'参数:strColumnName 字符串型 初始化的字段名称,其实可以算 ...

  7. 使用python脚本实现基于指定字符串的文本排序

    朋友用ansible导出了一个文件,文件中包含上千台机器的磁盘信息,他想要知道哪些机器最需要赶紧扩磁盘.思路是,按剩余磁盘空间百分数,从小到大对文本内容重新排序.下面是具体实现. 源文件ip.txt的 ...

  8. Dede后台验证码不显示解决方法详解(dedecms 5.7)

    今天朋友问我他本地与服务器上安装了dedecms5.7无法显示验证码,一般这种情况很少见,一般情况就是服务器设置问题,还有临时目录的权限问题 Dede后台验证码不显示或不正常分三种情况,下面来逐一分析 ...

  9. JS 和 CSS 的位置对其他资源加载顺序的影响

    JS 和 CSS 在页面中的位置,会影响其他资源(指 img 等非 js 和 css 资源)的加载顺序,究其原因,有三个值得注意的点: JS 有可能会修改 DOM. 典型的,可能会有 document ...

  10. JAVA设计模式--State(状态模式)

    状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要 ...