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

一、自定义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. [日常]总结2016年7月入职至2016年7月26号微盘所遇bug

    2016年刚入职后在新浪微盘项目上所遇到的问题: 1.前端接口的程序不同版本问题,版本号在程序路径中区分,比如2.4.2/lib/sdk/api/weipan/Client.php 2.文件夹接口的m ...

  2. [angularjs] angularjs系列笔记(五)Service

    AngularJs中你可以使用自己的服务或使用内建服务,服务是一个函数或对象,以下代码试验$location服务,$http服务,$timeout服务,$intverval服务,创建自定义服务 < ...

  3. 12.QT4.7.4-解决WIN平台和Linux平台中文乱码,QLineEdit右击菜单中文显示

    1.解决Win平台中文显示 1.1首先解决win平台上中文显示乱码问题 1)首先查看qt creator的编码格式 通过->编辑->选择编码 查看. 2)如果qt creator的编码格式 ...

  4. 《从Paxos到ZooKeeper 分布式一致性原理与实践》读书笔记

    一.分布式架构 1.分布式特点 分布性 对等性.分布式系统中的所有计算机节点都是对等的 并发性.多个节点并发的操作一些共享的资源 缺乏全局时钟.节点之间通过消息传递进行通信和协调,因为缺乏全局时钟,很 ...

  5. eclipse提交到git

    前言 今天是我正式加入GitHub的第一天,作为世界上最大的同性交友社区,以push和pull出名的它,让我坠入其中并无法自拔,废话不多说,上教程: 步骤一 首先,你需要注册一个github账号,相信 ...

  6. WPF中在XAML中实现数据类型转换的两种方法

    熟悉数据绑定的朋友都知道,当我们在Model中获取一个对象的数据,常常需要对其进行数据转换后显示在UI界面上,比如你用bool类型存储了一个人的性别,但是在界面上却需要经过转化后显示为男或女: 今天又 ...

  7. 老王带你走过 Kafka 入门教程

    Apache Kafka是分布式发布-订阅消息系统,在 kafka官网上对 kafka 的定义:一个分布式发布-订阅消息传递系统. 它最初由LinkedIn公司开发. Linkedin于2010年贡献 ...

  8. Grunt 入门操作指南

    0.简介 grunt是一个任务自动运行器.简单来讲,用了以后,再也不用每次修改sass后,去生成下css,也再也不用去一遍遍压缩js了 ,也再也不用修改了点点东西就要去刷新页面,也不需要去复杂地建立一 ...

  9. AOJ1370: Hidden Anagrams(hash)

    题意 题目链接 Sol 直接对出现的次数hash即可,复杂度\(O(26n^2)\) 一开始没判长度条件疯狂wa #include<bits/stdc++.h> //#define int ...

  10. Tars 负载均衡

    // 传入主控地址,在 db_tars t_registry_info 表中 Communicator communicator = CommunicatorFactory.getInstance() ...