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

一、自定义MButton

  • 控件外观控制的属性,如圆角、鼠标悬浮前景色背景色、是否开启动画(鼠标悬停时小图标转一圈,移开又转回去)、鼠标按下颜色等;
  • 字体图标相关属性,如字符值、字体图标大小、字体图标间距等。
  • 首先重写要修改的属性和添加要扩展的功能(在.cs中)
  •     public partial class MButton : Button
    {
    public static readonly DependencyProperty PressedBackgroundProperty =
    DependencyProperty.Register("PressedBackground", typeof(Brush), typeof(MButton), new PropertyMetadata(Brushes.DarkBlue));
    /// <summary>
    /// 鼠标按下背景样式
    /// </summary>
    public Brush PressedBackground
    {
    get { return (Brush)GetValue(PressedBackgroundProperty); }
    set { SetValue(PressedBackgroundProperty, value); }
    } public static readonly DependencyProperty PressedForegroundProperty =
    DependencyProperty.Register("PressedForeground", typeof(Brush), typeof(MButton), new PropertyMetadata(Brushes.White));
    /// <summary>
    /// 鼠标按下前景样式(图标、文字)
    /// </summary>
    public Brush PressedForeground
    {
    get { return (Brush)GetValue(PressedForegroundProperty); }
    set { SetValue(PressedForegroundProperty, value); }
    } public static readonly DependencyProperty MouseOverBackgroundProperty =
    DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(MButton), new PropertyMetadata(Brushes.RoyalBlue));
    /// <summary>
    /// 鼠标进入背景样式
    /// </summary>
    public Brush MouseOverBackground
    {
    get { return (Brush)GetValue(MouseOverBackgroundProperty); }
    set { SetValue(MouseOverBackgroundProperty, value); }
    } public static readonly DependencyProperty MouseOverForegroundProperty =
    DependencyProperty.Register("MouseOverForeground", typeof(Brush), typeof(MButton), new PropertyMetadata(Brushes.White));
    /// <summary>
    /// 鼠标进入前景样式
    /// </summary>
    public Brush MouseOverForeground
    {
    get { return (Brush)GetValue(MouseOverForegroundProperty); }
    set { SetValue(MouseOverForegroundProperty, value); }
    } public static readonly DependencyProperty CornerRadiusProperty =
    DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(MButton), new PropertyMetadata(new CornerRadius(2)));
    /// <summary>
    /// 按钮圆角大小,左上,右上,右下,左下
    /// </summary>
    public CornerRadius CornerRadius
    {
    get { return (CornerRadius)GetValue(CornerRadiusProperty); }
    set { SetValue(CornerRadiusProperty, value); }
    } public static readonly DependencyProperty ContentDecorationsProperty = DependencyProperty.Register(
    "ContentDecorations", typeof(TextDecorationCollection), typeof(MButton), new PropertyMetadata(null));
    public TextDecorationCollection ContentDecorations
    {
    get { return (TextDecorationCollection)GetValue(ContentDecorationsProperty); }
    set { SetValue(ContentDecorationsProperty, value); }
    } static FButton()
    {
    DefaultStyleKeyProperty.OverrideMetadata(typeof(FButton), new FrameworkPropertyMetadata(typeof(FButton)));
    }
    }

      

下面是模板:

<!--MButton模板-->
<ControlTemplate x:Key="FButton_Template" TargetType="{x:Type local:MButton}">
<Border x:Name="border" Background="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Background}"
Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Height}"
CornerRadius="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=CornerRadius}"
Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Width}"> Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= FIcon}"
FontSize="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= FIconSize}"
Foreground="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Foreground}">
<TextBlock.RenderTransform>
<RotateTransform x:Name="transIcon" Angle="0"/>
</TextBlock.RenderTransform>
</TextBlock> <TextBlock VerticalAlignment="Center" x:Name="txt"
TextDecorations="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ContentDecorations}"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}"
FontSize="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=FontSize}"
Foreground="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Foreground}"></TextBlock>
</StackPanel>
</Border>
<!--触发器-->
<ControlTemplate.Triggers>
<!--设置鼠标进入时的背景、前景样式-->
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
Path=MouseOverBackground}" TargetName="border" />
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
Path=MouseOverForeground}" TargetName="icon"/>
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
Path=MouseOverForeground}" TargetName="txt"/>
</Trigger> <!--鼠标按下时的前景、背景样式-->
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
Path=PressedBackground}" TargetName="border" />
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
Path=PressedForeground}" TargetName="icon"/>
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},
Path=PressedForeground}" TargetName="txt"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.5" TargetName="border"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

  

下面是样式:

<!--默认样式-->
<Style TargetType="{x:Type local:MButton}">
<Setter Property="Background" Value="{StaticResource ButtonBackground}" />
<Setter Property="Foreground" Value="{StaticResource ButtonForeground}" />
<Setter Property="MouseOverBackground" Value="{StaticResource ButtonMouseOverBackground}" />
<Setter Property="MouseOverForeground" Value="{StaticResource ButtonMouseOverForeground}" />
<Setter Property="PressedBackground" Value="{StaticResource ButtonPressedBackground}" />
<Setter Property="PressedForeground" Value="{StaticResource ButtonPressedForeground}" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="30" />
<Setter Property="FontSize" Value="13" />
<Setter Property="CornerRadius" Value="0" />
<Setter Property="Template" Value="{StaticResource FButton_Template}"/>
<Setter Property="Padding" Value="3,1,3,1" />
<Setter Property="Content" Value="{x:Null}" />
<Setter Property="AllowsAnimation" Value="False" />
</Style>

  

这样我们就万行了扩展Button

二、自定义TextBox

  这个TextBox可设置水印,可设置必填和正则表达式验证。

   就是在输入完成后,控件一旦失去焦点就会自动验证!会根据我开放出来的“是否可以为空”属性进行验证,一旦为空,则控件变为警告样式。

  但这还不是最特别的,为了各种手机号啊,邮箱啊的验证,我还开放了一个正则表达式的属性,在这个属性中填上正则表达式,同上, 一旦失去焦点就会自动验证输入的内容能否匹配正则表达式,如果不能匹配,则控件变为警告样式。

  之后,代码还可以通过我开放的另一个属性来判断当前输入框的输入是否有误。

 
 1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3 xmlns:ctrl="clr-namespace:KAN.WPF.XCtrl.Controls">
4 <Style TargetType="{x:Type ctrl:XTextBox}">
5 <!--StyleFocusVisual-->
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="BorderBrush" Value="Silver"/>
11 <Setter Property="BorderThickness" Value="1"/>
12 <Setter Property="Template">
13 <Setter.Value>
14 <ControlTemplate TargetType="{x:Type ctrl:XTextBox}">
15 <Border Name="brdText" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"
16 BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="true" Padding="2">
17 <Grid>
18 <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
19 <StackPanel Orientation="Horizontal" Visibility="Collapsed" Name="stpWatermark">
20 <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center"
21 FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}"
22 Foreground="{Binding XWmkForeground, RelativeSource={RelativeSource TemplatedParent}}"
23 Text="{Binding XWmkText, RelativeSource={RelativeSource TemplatedParent}}" Cursor="IBeam" />
24 </StackPanel>
25 <ContentPresenter></ContentPresenter>
26 </Grid>
27 </Border>
28 <ControlTemplate.Triggers>
29 <!--当失去焦点并且没有输入任何内容时-->
30 <MultiTrigger>
31 <MultiTrigger.Conditions>
32 <Condition Property="Text" Value=""/>
33 <Condition Property="IsFocused" Value="False"/>
34 </MultiTrigger.Conditions>
35 <MultiTrigger.Setters>
36 <Setter Property="Visibility" TargetName="stpWatermark" Value="Visible"/>
37 </MultiTrigger.Setters>
38 </MultiTrigger>
39 <!--当验证失败时-->
40 <Trigger Property="XIsError" Value="true">
41 <Setter TargetName="brdText" Property="BorderBrush" Value="Red" />
42 <Setter TargetName="brdText" Property="Background" Value="Beige" />
43 </Trigger>
44 </ControlTemplate.Triggers>
45 </ControlTemplate>
46 </Setter.Value>
47 </Setter>
48 </Style>
49 </ResourceDictionary>
 

  再来看看CS:

 
  1 using System;
2 using System.Windows;
3 using System.Windows.Controls;
4 using System.Windows.Media;
5 using System.Windows.Input;
6 using System.Text.RegularExpressions;
7
8 namespace KAN.WPF.XCtrl.Controls
9 {
10 /// <summary>
11 /// 扩展输入框:可设置水印,可设置必填,可设置正则表达式验证
12 /// </summary>
13 public class XTextBox:TextBox
14 {
15 #region 依赖属性
16 public static readonly DependencyProperty XWmkTextProperty;//水印文字
17 public static readonly DependencyProperty XWmkForegroundProperty;//水印着色
18 public static readonly DependencyProperty XIsErrorProperty;//是否字段有误
19 public static readonly DependencyProperty XAllowNullProperty;//是否允许为空
20 public static readonly DependencyProperty XRegExpProperty;//正则表达式
21 #endregion
22
23 #region 内部方法
24 /// <summary>
25 /// 注册事件
26 /// </summary>
27 public XTextBox()
28 {
29 this.LostFocus += new RoutedEventHandler(XTextBox_LostFocus);
30 this.GotFocus += new RoutedEventHandler(XTextBox_GotFocus);
31 this.PreviewMouseDown += new MouseButtonEventHandler(XTextBox_PreviewMouseDown);
32 }
33
34 /// <summary>
35 /// 静态构造函数
36 /// </summary>
37 static XTextBox()
38 {
39 //注册依赖属性
40 XTextBox.XWmkTextProperty = DependencyProperty.Register("XWmkText", typeof(String), typeof(XTextBox), new PropertyMetadata(null));
41 XTextBox.XAllowNullProperty = DependencyProperty.Register("XAllowNull", typeof(bool), typeof(XTextBox), new PropertyMetadata(true));
42 XTextBox.XIsErrorProperty = DependencyProperty.Register("XIsError", typeof(bool), typeof(XTextBox), new PropertyMetadata(false));
43 XTextBox.XRegExpProperty = DependencyProperty.Register("XRegExp", typeof(string), typeof(XTextBox), new PropertyMetadata(""));
44 XTextBox.XWmkForegroundProperty = DependencyProperty.Register("XWmkForeground", typeof(Brush),
45 typeof(XTextBox), new PropertyMetadata(Brushes.Silver));
46 FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata(typeof(XTextBox), new FrameworkPropertyMetadata(typeof(XTextBox)));
47 }
48
49 /// <summary>
50 /// 失去焦点时检查输入
51 /// </summary>
52 /// <param name="sender"></param>
53 /// <param name="e"></param>
54 void XTextBox_LostFocus(object sender, RoutedEventArgs e)
55 {
56 this.XIsError = false;
57 if (XAllowNull == false && this.Text.Trim() == "")
58 {
59 this.XIsError = true;
60 }
61 if (Regex.IsMatch(this.Text.Trim(), XRegExp) == false)
62 {
63 this.XIsError = true;
64 }
65 }
66
67 /// <summary>
68 /// 获得焦点时选中文字
69 /// </summary>
70 /// <param name="sender"></param>
71 /// <param name="e"></param>
72 void XTextBox_GotFocus(object sender, RoutedEventArgs e)
73 {
74 this.SelectAll();
75 }
76
77 /// <summary>
78 /// 鼠标点击时选中文字
79 /// </summary>
80 /// <param name="sender"></param>
81 /// <param name="e"></param>
82 void XTextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
83 {
84 if (this.IsFocused == false)
85 {
86 TextBox textBox = e.Source as TextBox;
87 textBox.Focus();
88 e.Handled = true;
89 }
90 }
91 #endregion
92
93 #region 公布属性
94 /// <summary>
95 /// 公布属性XWmkText(水印文字)
96 /// </summary>
97 public String XWmkText
98 {
99 get
100 {
101 return base.GetValue(XTextBox.XWmkTextProperty) as String;
102 }
103 set
104 {
105 base.SetValue(XTextBox.XWmkTextProperty, value);
106 }
107 }
108
109 /// <summary>
110 /// 公布属性XWmkForeground(水印着色)
111 /// </summary>
112 public Brush XWmkForeground
113 {
114 get
115 {
116 return base.GetValue(XTextBox.XWmkForegroundProperty) as Brush;
117 }
118 set
119 {
120 base.SetValue(XTextBox.XWmkForegroundProperty, value);
121 }
122 }
123
124 /// <summary>
125 /// 公布属性XIsError(是否字段有误)
126 /// </summary>
127 public bool XIsError
128 {
129 get
130 {
131 return (bool)base.GetValue(XTextBox.XIsErrorProperty);
132 }
133 set
134 {
135 base.SetValue(XTextBox.XIsErrorProperty, value);
136 }
137 }
138
139 /// <summary>
140 /// 公布属性XAllowNull(是否允许为空)
141 /// </summary>
142 public bool XAllowNull
143 {
144 get
145 {
146 return (bool)base.GetValue(XTextBox.XAllowNullProperty);
147 }
148 set
149 {
150 base.SetValue(XTextBox.XAllowNullProperty, value);
151 }
152 }
153
154 /// <summary>
155 /// 公布属性XRegExp(正则表达式)
156 /// </summary>
157 public string XRegExp
158 {
159 get
160 {
161 return base.GetValue(XTextBox.XRegExpProperty) as string;
162 }
163 set
164 {
165 base.SetValue(XTextBox.XRegExpProperty, value);
166 }
167 }
168 #endregion
169 }
170 }

好了,扩展控件就介绍完了

自定义控件系列博文链接:

WPF自定义控件(一)の控件分类
WPF自定义控件(二)の重写原生控件样式模板
WPF自定义控件(三)の扩展控件
WPF自定义控件(四)の自定义控件
WPF自定义控件(五)の用户控件

WPF自定义控件(三)の扩展控件的更多相关文章

  1. WPF自定义控件之图片控件 AsyncImage

    AsyncImage 是一个封装完善,使用简便,功能齐全的WPF图片控件,比直接使用Image相对来说更加方便,但它的内部仍然使用Image承载图像,只不过在其基础上进行了一次完善成熟的封装 Asyn ...

  2. WPF自定义控件二:Border控件与TextBlock控件轮播动画

    需求:实现Border轮播动画与TextBlock动画 XAML代码如下: <Window.Resources> <Storyboard x:Key="OnLoaded1& ...

  3. CYQ.Data 支持WPF相关的数据控件绑定(2013-08-09)

    事件的结果 经过多天的思考及忙碌的开发及测试,CYQ.Data 终于在UI上全面支持WPF,至此,CYQ.Data 已经可以方便支持wpf的开发,同时,框架仍保留最低.net framework2.0 ...

  4. CYQ.Data 支持WPF相关的数据控件绑定.Net获取iis版本

    CYQ.Data 支持WPF相关的数据控件绑定(2013-08-09) 事件的结果 经过多天的思考及忙碌的开发及测试,CYQ.Data 终于在UI上全面支持WPF,至此,CYQ.Data 已经可以方便 ...

  5. C# 自定义控件VS用户控件

    1 自定义控件与用户控件区别 WinForm中, 用户控件(User Control):继承自 UserControl,主要用于开发 Container 控件,Container控件可以添加其他Con ...

  6. 在WPF中使用WinForm控件方法

    1.      首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll. 2.      在要使用WinForm控 ...

  7. WPF中的image控件的Source赋值

    WPF中的Image控件Source的设置 1.XAML中 简单的方式(Source="haha.png"); image控件的Source设置为相对路径后(Source=&quo ...

  8. WPF后台设置xaml控件的样式System.Windows.Style

    WPF后台设置xaml控件的样式System.Windows.Style 摘-自 :感谢 作者: IT小兵   http://3w.suchso.com/projecteac-tual/wpf-zhi ...

  9. WPF Step By Step 控件介绍

    WPF Step By Step 控件介绍 回顾 上一篇,我们主要讨论了WPF的几个重点的基本知识的介绍,本篇,我们将会简单的介绍几个基本控件的简单用法,本文会举几个项目中的具体的例子,结合这些 例子 ...

随机推荐

  1. 关于laravel5 消息订阅/发布的理解初

    laravel5.4感觉官网文档说滴不够详细...安装predis官网很详细,这里略过.... 生成命令 直接使用 Artisan 命令 make:command,该命令会在 app/Console/ ...

  2. 为什么需要把页面放在WEB-INF文件夹下面?

    1.基于不同的功能 JSP 被放置在不同的目录下 这种方法的问题是这些页面文件容易被偷看到源代码,或被直接调用.某些场合下这可能不是个大问题,可是在特定情形中却可能构成安全隐患.用户可以绕过Strut ...

  3. Java中的方法重载与方法重写

    重载(overload) 重载是在一个类中,同名方法拥有不同的参数列表则视为重载.不同的参数列表包括:参数数量不同,参数类型不同,参数顺序不同.重载对于返回类型没有要求,所以不能通过返回类型去判断是否 ...

  4. 点到圆弧的距离(csu1503)+几何

    1503: 点到圆弧的距离 Time Limit: 1 Sec  Memory Limit: 128 MB  Special JudgeSubmit: 325  Solved: 70[Submit][ ...

  5. Netty 系列一(核心组件和实例).

    一.概念 早期的 Java API 只支持由本地系统套接字库提供所谓的阻塞函数来支持网络编程.由于是阻塞 I/O ,要管理多个并发客户端,需要为每个新的客户端Socket 创建一个 Thread .这 ...

  6. POJ 2407Relatives

    Relatives Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15566   Accepted: 7900 Descri ...

  7. Human Motion Analysis with Wearable Inertial Sensors——阅读3

    Human Motion Analysis with Wearable Inertial Sensors——阅读3 四元数方向滤波器 之前的研究开发了一种自适应增益互补滤波器,并结合高斯 - 牛顿优化 ...

  8. ViewPager实现滑动翻页效果

    实现ViewPager的滑动翻页效果可以使用ViewPager的setPageTransformer方法,如下: import android.content.Context; import andr ...

  9. 「Android」 Surface分析

    本篇针对Surface模块进行分析,从Java层的Activity创建开始,到ViewRoot.WindowsManagerService,再到JNI层和Native层. 首先推荐一个Android源 ...

  10. shell中的set、seq、eval、exec、&&和||

    一.set 查看set 帮助: bash -c "help set" 选项: -e:任何命令执行失败(非0 status)直接退出 -x: 打印执行过程的命令行.参数 +e:命令执 ...