一、查看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的更多相关文章

  1. 常用 Gulp 插件汇总 —— 基于 Gulp 的前端集成解决方案(三)

    前两篇文章讨论了 Gulp 的安装部署及基本概念,借助于 Gulp 强大的 插件生态 可以完成很多常见的和不常见的任务.本文主要汇总常用的 Gulp 插件及其基本使用,需要读者对 Gulp 有一个基本 ...

  2. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  3. Jquery的点击事件,三句代码完成全选事件

    先来看一下Js和Jquery的点击事件 举两个简单的例子 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...

  4. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  5. 简谈百度坐标反转至WGS84的三种思路

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 基于百度地图进行数据展示是目前项目中常见场景,但是因为百度地图 ...

  6. 一起学 Java(三) 集合框架、数据结构、泛型

    一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...

  7. 谈谈一些有趣的CSS题目(三)-- 层叠顺序与堆栈上下文知多少

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

  8. 如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域

    一.前言 结合我们本次系列的第一篇博文中提到的上下文映射图(传送门:如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念),得知我们这个电商网站的核心域就是销售子域.因为电子商务是以信息网络 ...

  9. 测试一下StringBuffer和StringBuilder及字面常量拼接三种字符串的效率

    之前一篇里写过字符串常用类的三种方式<java中的字符串相关知识整理>,只不过这个只是分析并不知道他们之间会有多大的区别,或者所谓的StringBuffer能提升多少拼接效率呢?为此写个简 ...

随机推荐

  1. uniapp微信小程序获取当前用户手机号码(前端)

    按钮触发获取用户信息 uniapp中与微信小程序官网所写会不同, <button open-type="getPhoneNumber" @getphonenumber=&qu ...

  2. Docker(3)- Centos 7.x 下 Docker 镜像加速配置

    如果你还想从头学起 Docker,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1870863.html 前言 默认情况下,Docker ...

  3. XJOI 夏令营501-511NOIP训练18 高二学堂

    在美丽的中山纪念中学中,有座高二学堂,同样也是因为一个人,让它们变 成了现在这个样子~那就是我们伟大的级主任.因为他,我们又迎来了一个木有电影,只有对答案的段考日:又迎来了一个不是大礼拜,而是小礼拜的 ...

  4. Linux sar命令参数详解

    转载自http://www.chinaz.com/server/2013/0401/297942.shtml sar(System Activity Reporter系统活动情况报告)是目前 Linu ...

  5. leetcode1Minimum Depth of Binary Tree

    题目描述 求给定二叉树的最小深度.最小深度是指树的根结点到最近叶子结点的最短路径上结点的数量. Given a binary tree, find its minimum depth.The mini ...

  6. layui表单一

    1. ***首先明确一点 表单的以来加载模块是 form.如果不加载form模块,select.checkbox.radio等将无法显示,并且无法使用form相关功能. 我们用layui官网的样本来做 ...

  7. tp3.2验证码

    切换验证码 document.getElementById('img_code_1').src="__URL__/verify/"+Math.random(1,9999); 生成验 ...

  8. [MIT6.006] 15. Single-Source Shortest Paths Problem 单一来源的最短路径问题

    首先简单介绍下最大路径问题:给定一个加权图,找到两点之间最短加权路径,本质上就是求两点之间哪条路径的权重和最小.有两种算法去做:Dijkatra和Bellman-Ford,后面几节课会专门讲这两个算法 ...

  9. Spring源码之Springboot中监听器介绍

    https://www.bilibili.com/video/BV12C4y1s7dR?p=11 监听器模式要素 事件 监听器 广播器 触发机制 Springboot中监听模式总结 在SpringAp ...

  10. linux常用配置文件和命令总结

    常用配置文件说明: 1..设置-n永远生效:Vim的配置文件:命令模式想永久生效, ~/.vimrc,新建文件,在里面输入保存即可 2.设置别名永远生效:在~/.bashrc  修改当前用户家目录里的 ...