WPF自定义控件(一)——Button

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

  先上图看看各种效果:

  这个Button是我继承系统Button后扩展的,主要实现了:可设置悬浮和按下时的背景,可改变形状,并可设置按钮按下后保持锁定状态等功能。

  这个Button我命名为XButton,扩展的所有属性我都会以X开头命名。好了,具体的东西看代码吧!

  先来Xaml的:

  

 1 <ResourceDictionary
 2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4     xmlns:ctrl="clr-namespace:KAN.WPF.XCtrl.Controls">
 5     <Style x:Key="{x:Type ctrl:XButton}" TargetType="{x:Type ctrl:XButton}">
 6         <Style.Resources>
 7             <ResourceDictionary Source="/KAN.WPF.Xctrl;component/Themes/CommonStyle.xaml"/>
 8         </Style.Resources>
 9         <Setter Property="FocusVisualStyle" Value="{StaticResource StyleFocusVisual}"/>
10         <Setter Property="Background" Value="White"/>
11         <Setter Property="BorderBrush" Value="Silver"/>
12         <Setter Property="BorderThickness" Value="1"/>
13         <Setter Property="Control.Template">
14             <Setter.Value>
15                 <ControlTemplate TargetType="{x:Type ctrl:XButton}">
16                     <!--定义视觉树-->
17                     <Grid>
18                         <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
19                             <!--这里的Path就是用来实现各种外形的-->
20                             <Path x:Name="bdrButton"
21                                    Data="{Binding XShape, RelativeSource={RelativeSource TemplatedParent}}"
22                                    Stroke="{Binding XStrokeBrush, RelativeSource={RelativeSource TemplatedParent}}"
23                                    StrokeThickness="{Binding XStrokeThickness, RelativeSource={RelativeSource TemplatedParent}}"
24                                    Stretch="Fill" RenderTransformOrigin="0.5,0.5" Fill="{TemplateBinding Control.Background}">
25                                 <Path.RenderTransform>
26                                     <TransformGroup>
27                                         <ScaleTransform/>
28                                         <SkewTransform/>
29                                         <RotateTransform/>
30                                         <TranslateTransform/>
31                                     </TransformGroup>
32                                 </Path.RenderTransform>
33                             </Path>
34                         </Border>
35                         <ContentPresenter Name="contentPresenter" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
36                                           ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Focusable="False" RecognizesAccessKey="True"
37                                           SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" Content="{TemplateBinding ContentControl.Content}"
38                                           HorizontalAlignment="Center" VerticalAlignment="Center" />
39                     </Grid>
40                     <!--设置触发器-->
41                     <ControlTemplate.Triggers>
42                         <!--鼠标移动上去时-->
43                         <Trigger Property="UIElement.IsMouseOver" Value="True" >
44                             <Setter TargetName="bdrButton" Value="{Binding XMoverBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
45                         </Trigger>
46                         <!--鼠标按下去时-->
47                         <Trigger Property="ButtonBase.IsPressed" Value="True">
48                             <Setter TargetName="bdrButton" Value="{Binding XEnterBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
49                         </Trigger>
50                         <!--禁用Button时-->
51                         <Trigger Property="IsEnabled" Value="false">
52                             <Setter TargetName="bdrButton" Value="{Binding XUnEnabledBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
53                         </Trigger>
54                         <!--如果设置了锁住按下的状态的属性,那么当按下时-->
55                         <MultiTrigger>
56                             <MultiTrigger.Conditions>
57                                 <Condition Property="IsFocused" Value="True"/>
58                                 <Condition Property="XIsFoucedBrushLock" Value="True"/>
59                             </MultiTrigger.Conditions>
60                             <MultiTrigger.Setters>
61                                 <Setter TargetName="bdrButton" Value="{Binding XEnterBrush, RelativeSource={RelativeSource TemplatedParent}}" Property="Path.Fill" />
62                             </MultiTrigger.Setters>
63                         </MultiTrigger>
64                     </ControlTemplate.Triggers>
65                 </ControlTemplate>
66             </Setter.Value>
67         </Setter>
68     </Style>
69 </ResourceDictionary>

  其中的StyleFocusVisual是用来定义按Tab到这个控件上的样式的,代码如下:

 1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 2                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 3     <Style x:Key="StyleFocusVisual">
 4         <Setter Property="Control.Template">
 5             <Setter.Value>
 6                 <ControlTemplate>
 7                     <Border Margin="0" BorderBrush="#FF9FBDF4" BorderThickness="1"/>
 8                 </ControlTemplate>
 9             </Setter.Value>
10         </Setter>
11     </Style>
12 </ResourceDictionary>

  接下来是CS的:

  

  1 using System;
  2 using System.Windows;
  3 using System.Windows.Controls;
  4 using System.Windows.Media;
  5 using System.Windows.Shapes;
  6 using System.Windows.Media.Imaging;
  7
  8 namespace KAN.WPF.XCtrl.Controls
  9 {
 10     /// <summary>
 11     /// 扩展按钮:可设置悬浮和按下时的背景,可改变形状,并可设置按钮按下后保持锁定状态
 12     /// </summary>
 13     public class XButton : Button
 14     {
 15         #region 依赖属性
 16         public static readonly DependencyProperty XMoverBrushProperty;//鼠标经过时的画刷
 17         public static readonly DependencyProperty XEnterBrushProperty;//鼠标按下时的画刷
 18         public static readonly DependencyProperty XUnEnabledBrushProperty;//禁用时的画刷
 19         public static readonly DependencyProperty XIsFoucedBrushLockProperty;//是否得到焦点时锁住画刷
 20         public static readonly DependencyProperty XShapeProperty;//外形的路径
 21         public static readonly DependencyProperty XStrokeBrushProperty;//外形的路径着色
 22         public static readonly DependencyProperty XStrokeThicknessProperty;//外形的路径粗细(默认为0,因为有Border边框,所以要设这个值,要先把BorderThickness设为0)
 23         #endregion
 24
 25         #region 内部方法
 26         /// <summary>
 27         /// 静态构造方法
 28         /// </summary>
 29         static XButton()
 30         {
 31             //注册依赖属性
 32             XButton.XMoverBrushProperty = DependencyProperty.Register("XMoverBrush", typeof(Brush), typeof(XButton),
 33                 new PropertyMetadata(Brushes.WhiteSmoke));
 34             XButton.XEnterBrushProperty = DependencyProperty.Register("XEnterBrush", typeof(Brush), typeof(XButton),
 35                 new PropertyMetadata(Brushes.Silver));
 36             XButton.XUnEnabledBrushProperty = DependencyProperty.Register("XUnEnabledBrush", typeof(Brush), typeof(XButton),
 37                 new PropertyMetadata(Brushes.Silver));
 38             XButton.XStrokeBrushProperty = DependencyProperty.Register("XStrokeBrush", typeof(Brush), typeof(XButton),
 39                 new PropertyMetadata(Brushes.Silver));
 40             XButton.XStrokeThicknessProperty = DependencyProperty.Register("XStrokeThickness", typeof(Double), typeof(XButton),
 41                 new PropertyMetadata(0.0));
 42             XButton.XIsFoucedBrushLockProperty = DependencyProperty.Register("XIsFoucedBrushLock", typeof(bool), typeof(XButton),
 43                 new PropertyMetadata(false));
 44             XButton.XShapeProperty = DependencyProperty.Register("XShape", typeof(string), typeof(XButton),
 45                 new PropertyMetadata("M 0 0 L 0 0 L 100 0 L 100 100 L 0 100 Z"));
 46             FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(XButton), new FrameworkPropertyMetadata(typeof(XButton)));
 47         }
 48         #endregion
 49
 50         #region 公布属性
 51         /// <summary>
 52         /// 公布属性XMoverBrush(鼠标经过时的画刷)
 53         /// </summary>
 54         public Brush XMoverBrush
 55         {
 56             get
 57             {
 58                 return base.GetValue(XButton.XMoverBrushProperty) as Brush;
 59             }
 60             set
 61             {
 62                 base.SetValue(XButton.XMoverBrushProperty, value);
 63             }
 64         }
 65
 66         /// <summary>
 67         /// 公布属性XMoverBrush(鼠标按下时的画刷)
 68         /// </summary>
 69         public Brush XEnterBrush
 70         {
 71             get
 72             {
 73                 return base.GetValue(XButton.XEnterBrushProperty) as Brush;
 74             }
 75             set
 76             {
 77                 base.SetValue(XButton.XEnterBrushProperty, value);
 78             }
 79         }
 80
 81         /// <summary>
 82         /// 公布属性XUnEnabledBrush(禁用时的画刷)
 83         /// </summary>
 84         public Brush XUnEnabledBrush
 85         {
 86             get
 87             {
 88                 return base.GetValue(XButton.XUnEnabledBrushProperty) as Brush;
 89             }
 90             set
 91             {
 92                 base.SetValue(XButton.XUnEnabledBrushProperty, value);
 93             }
 94         }
 95
 96         /// <summary>
 97         /// 公布属性XIsFoucedBrushLock(是否得到焦点时锁住画刷)
 98         /// </summary>
 99         public bool XIsFoucedBrushLock
100         {
101             get
102             {
103                 return (bool)base.GetValue(XButton.XIsFoucedBrushLockProperty);
104             }
105             set
106             {
107                 base.SetValue(XButton.XIsFoucedBrushLockProperty, value);
108             }
109         }
110
111         /// <summary>
112         /// 公布属性XShape(外形的路径)
113         /// </summary>
114         public String XShape
115         {
116             get
117             {
118                 return base.GetValue(XButton.XShapeProperty) as String;
119             }
120             set
121             {
122                 base.SetValue(XButton.XShapeProperty, value);
123             }
124         }
125
126         /// <summary>
127         /// 公布属性XStrokeBrush(外形的路径着色)
128         /// </summary>
129         public Brush XStrokeBrush
130         {
131             get
132             {
133                 return base.GetValue(XButton.XStrokeBrushProperty) as Brush;
134             }
135             set
136             {
137                 base.SetValue(XButton.XStrokeBrushProperty, value);
138             }
139         }
140
141         /// <summary>
142         /// 公布属性XStrokeThickness(外形的路径粗细)
143         /// </summary>
144         public Double XStrokeThickness
145         {
146             get
147             {
148                 return (Double)base.GetValue(XButton.XStrokeThicknessProperty);
149             }
150             set
151             {
152                 base.SetValue(XButton.XStrokeThicknessProperty, value);
153             }
154         }
155         #endregion
156     }
157 }

  看了代码上的注释应该都能明白吧!要是有不明白的可以留言。

  至于源代码,我之后会整理几个控件后一起发上来的!

时间: 2024-10-16 22:10:10

WPF自定义控件(一)——Button的相关文章

WPF自定义控件之带倒计时的按钮--Button

原文:WPF自定义控件之带倒计时的按钮--Button 1.说明 之前做过一个小项目,点击按钮,按钮进入倒计时无效状态,计时完成后,恢复原样,现在就实现该效果---带倒计时的按钮 2.效果 1)正常状态               2)MouseOver(只有背景色变化)         3)点击进入无效状态 4)在无效状态下计时              5)恢复正常状态 3.XAML代码 1 <!--冷却计时按钮样式--> <!--通过修改颜色值参数,以更改按钮颜色样式,更多修改,还

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

一.前言.效果图 还是先看看效果图吧:   定义Button按钮名称叫FButton,主要是集成了字体图标(参考上一篇:WPF自定义控件与样式1-矢量字体图标(iconfont)).其实在WPF里,要实现本文FButton的需求,完全可以不用自定义控件,使用样式.模板就可以搞定了的. 二.按钮FButton控件定义 2.1 FButton继承自微软基础控件Button (C#代码) FButton继承自微软基础控件Button,没有什么逻辑代码,主要扩展了几个属性: 控件外观控制的属性,如圆角.

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

一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 日历控件Calendar自定义样式: 日期控件DatePicker自定义样式,及Label标签.水印.清除日期功能扩展: 二.Calendar自定义样式 先看看效果: 从上面图可以看出,日历的显示其实有三种状态,如下面的分解图: "日"部分的显示: "月"部分的显示: &qu

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

原文:WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式.水印.Label标签.功能扩展 一.前言.预览 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要是对文本输入控件进行样式开发,及相关扩展功能开发,主要内容包括: 基本文本框TextBox控件样式及扩展功能,实现了样式.水印.Label标签.功能扩展: 富

WPF 自定义控件及样式

这次通过最近做的小例子说明一下自定义Button控件和样式. 实现的效果为: 在讲解之前先分析一下: 这上面为八个按钮,这是毫无疑问的.在每个按钮中又包含了一个图片和文本两个元素.虽然有这么多按钮,但他们的样式基本相同,除了按钮中的图片和文字内容.所以我们可以把相同的部分提取出来,把不同的内容进行传参来实现不同的效果. 继续分析,在按钮中包含的这两个元素,一个是图片元素,一个是文本元素.先说文本元素,文本元素直接可以通过Button.Content直接赋值.但Image控件的Source属性不能

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

原文:WPF自定义控件与样式(15)-终结篇 系列文章目录  WPF自定义控件与样式(1)-矢量字体图标(iconfont) WPF自定义控件与样式(2)-自定义按钮FButton WPF自定义控件与样式(3)-TextBox & RichTextBox & PasswordBox样式.水印.Label标签.功能扩展 WPF自定义控件与样式(4)-CheckBox/RadioButton自定义样式 WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展

wpf自定义控件中使用自定义事件

wpf自定义控件中使用自定义事件 1 创建自定义控件及自定义事件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36     /// <summary>     /// 演示用的自定义控件     /// </summary>     public class ExtButton : Button     {         public

[WPF自定义控件]从ContentControl开始入门自定义控件

原文:[WPF自定义控件]从ContentControl开始入门自定义控件 1. 前言 我去年写过一个在UWP自定义控件的系列博客,大部分的经验都可以用在WPF中(只有一点小区别).这篇文章的目的是快速入门自定义控件的开发,所以尽量精简了篇幅,更深入的概念在以后介绍各控件的文章中实际运用到才介绍. ContentControl是WPF中最基础的一种控件,Window.Button.ScrollViewer.Label.ListBoxItem等都继承自ContentControl.而且Conten

[WPF 自定义控件]创建包含CheckBox的ListBoxItem

原文:[WPF 自定义控件]创建包含CheckBox的ListBoxItem 1. 前言# Xceed wpftoolkit提供了一个CheckListBox,效果如下: 不过它用起来不怎么样,与其这样还不如参考UWP的ListView实现,而且动画效果也很好看: 它的样式如下: Copy <ListViewItemPresenter ContentTransitions="{TemplateBinding ContentTransitions}" x:Name="Ro

WPF自定义控件与样式(11)-等待/忙/正在加载状态-控件实现

一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要有三种实现方式: 简单忙碌状态控件BusyBox: Win8/win10效果忙碌状态控件ProgressRing: 弹出异步等待框WaitingBox: 二.简单忙碌状态控件BusyBox 效果图: 通过属性"IsActive"控制控件是否启用,后台C#代码: /// <summary> /