WPF自定义控件(三)の扩展控件
扩展控件,顾名思义就是对已有的控件进行扩展,一般继承于已有的原生控件,不排除继承于自定义的控件,不过这样做意义不大,因为既然都自定义了,为什么不一步到位呢,有些不同的需求也可以通过此来完成,不过类似于类继承了。扩展控件本质也是类的继承。下面我们通过两个例子说明
一、自定义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自定义控件(三)の扩展控件的更多相关文章
- WPF自定义控件之图片控件 AsyncImage
AsyncImage 是一个封装完善,使用简便,功能齐全的WPF图片控件,比直接使用Image相对来说更加方便,但它的内部仍然使用Image承载图像,只不过在其基础上进行了一次完善成熟的封装 Asyn ...
- WPF自定义控件二:Border控件与TextBlock控件轮播动画
需求:实现Border轮播动画与TextBlock动画 XAML代码如下: <Window.Resources> <Storyboard x:Key="OnLoaded1& ...
- CYQ.Data 支持WPF相关的数据控件绑定(2013-08-09)
事件的结果 经过多天的思考及忙碌的开发及测试,CYQ.Data 终于在UI上全面支持WPF,至此,CYQ.Data 已经可以方便支持wpf的开发,同时,框架仍保留最低.net framework2.0 ...
- CYQ.Data 支持WPF相关的数据控件绑定.Net获取iis版本
CYQ.Data 支持WPF相关的数据控件绑定(2013-08-09) 事件的结果 经过多天的思考及忙碌的开发及测试,CYQ.Data 终于在UI上全面支持WPF,至此,CYQ.Data 已经可以方便 ...
- C# 自定义控件VS用户控件
1 自定义控件与用户控件区别 WinForm中, 用户控件(User Control):继承自 UserControl,主要用于开发 Container 控件,Container控件可以添加其他Con ...
- 在WPF中使用WinForm控件方法
1. 首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll. 2. 在要使用WinForm控 ...
- WPF中的image控件的Source赋值
WPF中的Image控件Source的设置 1.XAML中 简单的方式(Source="haha.png"); image控件的Source设置为相对路径后(Source=&quo ...
- WPF后台设置xaml控件的样式System.Windows.Style
WPF后台设置xaml控件的样式System.Windows.Style 摘-自 :感谢 作者: IT小兵 http://3w.suchso.com/projecteac-tual/wpf-zhi ...
- WPF Step By Step 控件介绍
WPF Step By Step 控件介绍 回顾 上一篇,我们主要讨论了WPF的几个重点的基本知识的介绍,本篇,我们将会简单的介绍几个基本控件的简单用法,本文会举几个项目中的具体的例子,结合这些 例子 ...
随机推荐
- Core知识整理
概述 Commond-Line ASP.NET结构文件 Startup 配置文件 中间件和依赖注入 依赖注入原理 框架自带的依赖注入(IServiceCollection) 依赖注入生命周期 依赖注入 ...
- js正则表达式 URL格式匹配详解
0.URL格式 protocol :// hostname[:port] / path / [;parameters][?query]#fragment [;parameters]没见过 这里就不做相 ...
- CSS3 画基本图形,圆形、椭圆形、三角形等
CSS3圆角#css3-circle{ width: 150px; height: 150px; border-radius: 50%; }CSS3 椭圆形css3 radius#css3-elips ...
- 初学HTML-1
HTML:Hyper Text Markup Language的缩写 超文本标记语言,用来描述文本的语义,这些文本———超文本,也叫标签. 基本格式: <html> <head ...
- Spring的原理性总结
一.Bean的生命过程 Bean的生命过程可以借鉴Servlet的生命过程,了解其生命过程对于不管是思想还是以后的使用都很有帮助: Bean可以通过两种方式进行加载,分别是使用BeanFactory ...
- Space Time Varying Color Palette
PDF Space Time Varying Color Palettes from Bo Zhou
- UVA 1152 4 Values whose Sum is 0 (枚举+中途相遇法)(+Java版)(Java手撕快排+二分)
4 Values whose Sum is 0 题目链接:https://cn.vjudge.net/problem/UVA-1152 ——每天在线,欢迎留言谈论. 题目大意: 给定4个n(1< ...
- javascript的介绍、javascirpt的存在形式、javascript注释
本文内容: javascript的介绍 javascirpt的存在形式 javascript注释 javascript的介绍: javascript是一种解释性脚本语言 它的用途是给html网页增加动 ...
- mysql之外键
本文内容: 什么是外键 外键的增加 外键的修改和删除 外键的约束模式 首发日期:2018-04-12 什么是外键: 外键就是表中存在一个字段指向另外一个表的主键,那么这个字段就可以称为外键. 一张表可 ...
- 【软件需求工程与建模 - 小组项目】第6周 - 成果展示2 - 软件需求规格说明书V4.3
成果展示2 - 软件需求规格说明书V4.3