Cys_Control(三) MTextBox
一、查看TextBox原样式
通过Blend查看TextBox原有样式
<Window.Resources>
<SolidColorBrush x:Key="TextBox.Static.Border" Color="#FFABAdB3"/>
<SolidColorBrush x:Key="TextBox.MouseOver.Border" Color="#FF7EB4EA"/>
<SolidColorBrush x:Key="TextBox.Focus.Border" Color="#FF569DE5"/>
<Style x:Key="TextBoxStyle1" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
<Condition Property="IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
</MultiTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
分析 ControlTemplate 可知 TextBox由 ScrollViewer 外加边框组成
<Border x:Name="border" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Border>
二、优化原有样式
1、增加圆角控制
如何控制Border圆角?我们知道TextBox的宽高都有依赖属性控制,但并没有控制Border圆角的依赖属性,因此我们需要为其增加控制圆角的依赖属性
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(MTextBox),
new PropertyMetadata(new CornerRadius(0)));
/// <summary>
/// CornerRadius 圆角
/// </summary>
public CornerRadius CornerRadius
{
get => (CornerRadius)GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
}
Xaml中需要增加依赖属性绑定
<Border x:Name="PART_Border" CornerRadius="{TemplateBinding CornerRadius}"/>

2、增加水印
增加水印可以在原有的 ScrollViewer 上增加一层文本遮罩可以使用TextBlock 调整样式代码如下
<Border x:Name="PART_Border" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
<Grid>
<ScrollViewer x:Name="PART_ContentHost" FontSize="{TemplateBinding FontSize}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" BorderThickness="0" IsTabStop="False"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="4,0"/>
<!--水印-->
<TextBlock x:Name="Part_Watermark" Text="请输入内容" FontSize="{TemplateBinding FontSize}" Visibility="Hidden" HorizontalAlignment="Left"
Foreground="{DynamicResource ColorBrush.FontWatermarkColor}" IsHitTestVisible="False" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="5,0"/>
</Grid>
</Border>
此时遮罩已加好,但我们还要控制水印的显示,当有文本时不显示水印,当无文本时显示水印,此时需要使用触发器判断Text属性 如下
<!--显示水印-->
<Trigger Property="Text" Value="">
<Setter TargetName="Part_Watermark" Property="Visibility" Value="Visible" />
</Trigger>

增加依赖属性Water
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(string), typeof(MTextBox));
/// <summary>
/// Watermark 水印
/// </summary>
public string Watermark
{
get => (string)GetValue(WatermarkProperty);
set => SetValue(WatermarkProperty, value);
}
xaml增加绑定
<TextBlock x:Name="Part_Watermark" Text="{TemplateBinding Watermark}" FontSize="{TemplateBinding FontSize}" Visibility="Hidden" HorizontalAlignment="Left"
Foreground="{DynamicResource ColorBrush.FontWatermarkColor}" IsHitTestVisible="False" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="5,0"/>
3、增加ICON
增加依赖属性Icon用于Image绑定
public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(BitmapImage), typeof(MTextBox),
new PropertyMetadata(null));
/// <summary>
/// Icon 图标
/// </summary>
public BitmapImage Icon
{
get => (BitmapImage)GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
继续调整模板样式增加Image
<Grid VerticalAlignment="Center">
<Border x:Name="PART_Border" CornerRadius="{TemplateBinding CornerRadius}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"
SnapsToDevicePixels="true">
</Border>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<!--Icon-->
<Image HorizontalAlignment="Left" x:Name="PART_Icon" Height="16" Width="16" Margin="5,0,0,0" Source="{TemplateBinding Icon}"/>
</Grid>
<Grid Grid.Column="1">
<ScrollViewer x:Name="PART_ContentHost" FontSize="{TemplateBinding FontSize}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" BorderThickness="0" IsTabStop="False"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="4,0"/>
<!--水印-->
<TextBlock x:Name="Part_Watermark" Text="{TemplateBinding Watermark}" FontSize="{TemplateBinding FontSize}" Visibility="Hidden" HorizontalAlignment="Left"
Foreground="{DynamicResource ColorBrush.FontWatermarkColor}" IsHitTestVisible="False" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="5,0"/>
</Grid>
</Grid>
</Grid>
当无Icon时应使图片不占用位置,故增加属性触发器处理
<!--隐藏Icon-->
<Trigger SourceName="PART_Icon" Property="Source" Value="{x:Null}">
<Setter TargetName="PART_Icon" Property="Visibility" Value="Collapsed" />
</Trigger>
4、增加选中效果
TextBox增加阴影处理,默认状态透明度为0
<Border.Effect>
<DropShadowEffect x:Name="PART_DropShadow" BlurRadius="5" ShadowDepth="0" Color="{TemplateBinding FocusedBrush}" Opacity="0"/>
</Border.Effect>
增加属性触发器
当isFocused为True时使阴影Opacity为1,此处增加StoryBoard 使Opacity显示变化平滑一些
<Trigger Property="IsFocused" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_DropShadow" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.15">
<DoubleAnimation.EasingFunction>
<BackEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_DropShadow" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.15">
<DoubleAnimation.EasingFunction>
<BackEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>

三、源码地址
gitee地址:https://gitee.com/sirius_machao/Cys_Controls/tree/dev/
Cys_Control(三) MTextBox的更多相关文章
- 常用 Gulp 插件汇总 —— 基于 Gulp 的前端集成解决方案(三)
前两篇文章讨论了 Gulp 的安装部署及基本概念,借助于 Gulp 强大的 插件生态 可以完成很多常见的和不常见的任务.本文主要汇总常用的 Gulp 插件及其基本使用,需要读者对 Gulp 有一个基本 ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- Jquery的点击事件,三句代码完成全选事件
先来看一下Js和Jquery的点击事件 举两个简单的例子 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...
- node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理
一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...
- 简谈百度坐标反转至WGS84的三种思路
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 基于百度地图进行数据展示是目前项目中常见场景,但是因为百度地图 ...
- 一起学 Java(三) 集合框架、数据结构、泛型
一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...
- 谈谈一些有趣的CSS题目(三)-- 层叠顺序与堆栈上下文知多少
开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...
- 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域
一.前言 结合我们本次系列的第一篇博文中提到的上下文映射图(传送门:如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念),得知我们这个电商网站的核心域就是销售子域.因为电子商务是以信息网络 ...
- 测试一下StringBuffer和StringBuilder及字面常量拼接三种字符串的效率
之前一篇里写过字符串常用类的三种方式<java中的字符串相关知识整理>,只不过这个只是分析并不知道他们之间会有多大的区别,或者所谓的StringBuffer能提升多少拼接效率呢?为此写个简 ...
随机推荐
- Spring源码笔记
Spring Version:5.1.12 ApplicationContext 常用的实例化方式: ClassPathXmlApplicationContext FileSystemXmlAppli ...
- 按揭贷款的计算原理与java实现
Number部分(6) Mortgage Calculator--按揭贷款计算器 题目描述: Mortgage Calculator – Calculate the monthly payments ...
- ubunutu16.04 更改普通用户权限注销后只有guest身份 没有用户身份
第一次踩进百度经验的坑..... 之前对百度经验百信不疑,现在怀疑人生.. 网上搜了很多,也变得小心翼翼,最后姑且相信,但还是有点出入,以下是我的实践: (1)重启ubuntu系统,长按shift进入 ...
- streamreader
using (StreamReader sr = new StreamReader(@"C:\Documents and Settings\Administrator\桌面\1.txt&qu ...
- nginx安装 linux
1.安装依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 2.创建一个文件夹 cd /usr/local m ...
- nginx&http 第三章 ngx 事件event accept epoll /init
tcp 三次握手成功后,listen fd 可读,在process_event_timer 中调用rev->handler(rev)处理: 其回调函数为: ngx_event_accept / ...
- JS变量、作用域和内存问题
一.基本类型和引用类型 1. 基本类型值指的是简单的数据段,引用类型值指那些可能由多个值组成的对象. 2. 基本类型值按值访问,引用类型值按引用访问: 按值访问对于基本类型而言,不同变量指向的地址空间 ...
- parted命令采用gpt分区过程
Gpt无分区限制,故只有主分区,无扩展分区和逻辑分区.分区直接按容量算,不按柱面算. 查看分区:parted -l 将分区表类型转换为gpt.: 主要命令mklabel gpt 对sdc盘分区: [r ...
- ubuntu服务器dns重启失效问题
方法一 通过/etc/network/interfaces,在它的最后增加一句: dns-nameservers 8.8.8.8 8.8.8.8是Google提供的DNS服务,这里只是举一个例子,你也 ...
- Dubbo 服务导出-Version2.7.5
1.源码分析 1.1分析服务导出入口 当容器为spring是dubbo会为容器注册两个监听器:DubboLifecycleComponentApplicationListener和DubboBoots ...