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 }

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

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

posted @ 2014-11-04 22:13  覃宇琨  阅读(8740)  评论(1编辑  收藏  举报