WPF 带水印的密码输入框实现
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/BYH371256/article/details/83505584
本章讲述:带水印的密码输入框实现
主要功能:带水印效果,控件提示图标,控件文本清除图标;
新建一个WPF项目,然后添加“自定义控件(WPF)”,命名为:“ExTextBox”
资源字典XAML前台样式
<Style TargetType="{x:Type local:ExTextBox}">
	<Setter Property="VerticalAlignment" Value="Center"/>
	<Setter Property="VerticalContentAlignment" Value="Center"/>
	<Setter Property="BorderThickness" Value="1"/>
	<Setter Property="BorderBrush" Value="Gray"/>
	<Setter Property="Cursor" Value="IBeam"/>
	<Setter Property="Padding" Value="3,0,0,0"/>
	<Setter Property="Template">
		<Setter.Value>
			<ControlTemplate TargetType="{x:Type local:ExTextBox}">
				<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
						Background="{TemplateBinding Background}" CornerRadius="{TemplateBinding BorderCornerRadius}"
						SnapsToDevicePixels="True">
					<Grid x:Name="gdpassword">
						<Grid.ColumnDefinitions>
							<ColumnDefinition Width="auto"/>
							<ColumnDefinition Width="*"/>
							<ColumnDefinition Width="auto"/>
						</Grid.ColumnDefinitions>
						<Image x:Name="TipImage" Source="{Binding TipImage, RelativeSource={RelativeSource TemplatedParent}}"
							   Height="{Binding ImageSize, RelativeSource={RelativeSource TemplatedParent}}" Margin="0,2,0,0"
							   Width="{Binding ImageSize, RelativeSource={RelativeSource TemplatedParent}}"
							   Visibility="{Binding TipImageHide,RelativeSource={RelativeSource TemplatedParent}}"/>
						<Grid Grid.Column="1">
							<ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
							<TextBlock x:Name="txtRemark" Text="{TemplateBinding WaterRemark}" Foreground="Gray" VerticalAlignment="Center"
								   Margin="{TemplateBinding Padding}" Visibility="Collapsed"/>
						</Grid>
						<Image x:Name="OperateImage" Grid.Column="2" Source="{Binding OperateImage, RelativeSource={RelativeSource TemplatedParent}}"
							   Height="{Binding ImageSize, RelativeSource={RelativeSource TemplatedParent}}" Margin="0,2,0,0"
							   Width="{Binding ImageSize, RelativeSource={RelativeSource TemplatedParent}}" Cursor="Hand"
							   Visibility="{Binding OperateHide,RelativeSource={RelativeSource TemplatedParent}}"
							   />
					</Grid>
				</Border>
				<ControlTemplate.Triggers>
					<Trigger Property="Text" Value="">
						<Setter Property="Visibility" Value="Visible" TargetName="txtRemark"/>
					</Trigger>
				</ControlTemplate.Triggers>
			</ControlTemplate>
		</Setter.Value>
	</Setter>
</Style>
实现
public class ExTextBox : TextBox        //1.首先创建一个类,继承TextBox
    {
        //2.指定依赖属性的实例重写基类型的元数据
        static ExTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ExTextBox), new FrameworkPropertyMetadata(typeof(ExTextBox)));
        }
        Image OperateImageE;
        Image TipImageE;
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            var bord = VisualTreeHelper.GetChild(this, 0) as Border;
            Grid gr = bord.FindName("gdpassword") as Grid;
            TipImageE = gr.FindName("TipImage") as Image;
            OperateImageE = gr.FindName("OperateImage") as Image;
            //TipImageE.PreviewMouseLeftButtonUp +=TipImageE_PreviewMouseLeftButtonUp;
            OperateImageE.PreviewMouseLeftButtonUp +=OperateImageE_PreviewMouseLeftButtonUp;
        }
        private void OperateImageE_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.Text = "";
        }
        //3.定义依赖属性 
        public static DependencyProperty WaterRemarkProperty =
            DependencyProperty.Register("WaterRemark", typeof(string), typeof(ExTextBox));
        /// <summary>
        /// 水印文字
        /// </summary>
        public string WaterRemark
        {
            get { return GetValue(WaterRemarkProperty).ToString(); }
            set { SetValue(WaterRemarkProperty, value); }
        }
        public static DependencyProperty BorderCornerRadiusProperty =
            DependencyProperty.Register("BorderCornerRadius", typeof(CornerRadius), typeof(ExTextBox));
        /// <summary>
        /// 边框角度
        /// </summary>
        public CornerRadius BorderCornerRadius
        {
            get { return (CornerRadius)GetValue(BorderCornerRadiusProperty); }
            set { SetValue(BorderCornerRadiusProperty, value); }
        }
        public static DependencyProperty IsPasswordBoxProperty =
            DependencyProperty.Register("IsPasswordBox", typeof(bool), typeof(ExTextBox), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsPasswordBoxChnage)));
        /// <summary>
        /// 是否为密码框
        /// </summary>
        public bool IsPasswordBox
        {
            get { return (bool)GetValue(IsPasswordBoxProperty); }
            set { SetValue(IsPasswordBoxProperty, value); }
        }
        public static DependencyProperty PasswordCharProperty =
            DependencyProperty.Register("PasswordChar", typeof(char), typeof(ExTextBox), new FrameworkPropertyMetadata('●'));
        /// <summary>
        /// 替换明文的单个密码字符
        /// </summary>
        public char PasswordChar
        {
            get { return (char)GetValue(PasswordCharProperty); }
            set { SetValue(PasswordCharProperty, value); }
        }
        public static DependencyProperty PasswordStrProperty =
            DependencyProperty.Register("PasswordStr", typeof(string), typeof(ExTextBox), new FrameworkPropertyMetadata(string.Empty));
        /// <summary>
        /// 密码字符串
        /// </summary>
        public string PasswordStr
        {
            get { return GetValue(PasswordStrProperty).ToString(); }
            set { SetValue(PasswordStrProperty, value); }
        }
        /// <summary>
        /// 图标大小
        /// </summary>
        public double ImageSize
        {
            get { return (double)GetValue(ImageSizeProperty); }
            set { SetValue(ImageSizeProperty, value); }
        }
        public static readonly DependencyProperty ImageSizeProperty =
            DependencyProperty.Register("ImageSize", typeof(double), typeof(ExTextBox),
            new FrameworkPropertyMetadata(26.0, FrameworkPropertyMetadataOptions.AffectsRender));
        public static readonly DependencyProperty TipImageProperty = DependencyProperty.Register(
              "TipImage",
              typeof(string),
              typeof(ExTextBox),
              new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender, ImageSourceChanged));
        /// <summary>
        ///
        /// <summary>
        public string TipImage
        {
            get { return (string)GetValue(TipImageProperty); }
            set { SetValue(TipImageProperty, value); }
        }
        public static readonly DependencyProperty OperateImageProperty = DependencyProperty.Register(
                      "OperateImage",
                      typeof(string),
                      typeof(ExTextBox),
                      new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender, ImageSourceChanged));
        /// <summary>
        ///
        /// <summary>
        public string OperateImage
        {
            get { return (string)GetValue(OperateImageProperty); }
            set { SetValue(OperateImageProperty, value); }
        }
        public static readonly DependencyProperty TipImageHideProperty = DependencyProperty.Register(
              "TipImageHide",
              typeof(Visibility),
              typeof(ExTextBox),
              new FrameworkPropertyMetadata(Visibility.Collapsed));
        /// <summary>
        ///
        /// <summary>
        public Visibility TipImageHide
        {
            get { return (Visibility)GetValue(TipImageHideProperty); }
            set { SetValue(TipImageHideProperty, value); }
        }
        public static readonly DependencyProperty OperateHideProperty = DependencyProperty.Register(
                      "OperateHide",
                      typeof(Visibility),
                      typeof(ExTextBox),
                      new FrameworkPropertyMetadata(Visibility.Collapsed));
        /// <summary>
        ///
        /// <summary>
        public Visibility OperateHide
        {
            get { return (Visibility)GetValue(OperateHideProperty); }
            set { SetValue(OperateHideProperty, value); }
        }
        //依赖属性发生改变时候触发
        private static void ImageSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            Application.GetResourceStream(new Uri((string)e.NewValue));
            if(e.Property.Name == "TipImage")
            {
                (sender as ExTextBox).TextBox_Changed(0);
            }
            if (e.Property.Name == "OperateImage")
            {
                (sender as ExTextBox).TextBox_Changed(1);
            }
        }
        private void TextBox_Changed(int index)
        {
            if (index == 0)
                TipImageHide = Visibility.Visible;
            else
                OperateHide = Visibility.Visible;
        }
        //4.当设置为密码框时,监听TextChange事件,处理Text的变化,这是密码框的核心功能
        private static void OnIsPasswordBoxChnage(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            (sender as ExTextBox).SetEvent();
        }
        /// <summary>
        /// 定义TextChange事件
        /// </summary>
        private void SetEvent()
        {
            if (IsPasswordBox)
                this.TextChanged += TextBox_TextChanged;
            else
                this.TextChanged -= TextBox_TextChanged;
        }
        //5.在TextChange事件中,处理Text为密码文,并将原字符记录给PasswordStr予以存储
        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (!IsResponseChange) //响应事件标识,替换字符时,不处理后续逻辑
                return;
            //Console.WriteLine(string.Format("------{0}------", e.Changes.Count));
            foreach (TextChange c in e.Changes)
            {
                //Console.WriteLine(string.Format("addLength:{0} removeLenth:{1} offSet:{2}", c.AddedLength, c.RemovedLength, c.Offset));
                PasswordStr = PasswordStr.Remove(c.Offset, c.RemovedLength); //从密码文中根据本次Change对象的索引和长度删除对应个数的字符
                PasswordStr = PasswordStr.Insert(c.Offset, Text.Substring(c.Offset, c.AddedLength));   //将Text新增的部分记录给密码文
                lastOffset = c.Offset;
            }
            //Console.WriteLine(PasswordStr);
            /*将文本转换为密码字符*/
            IsResponseChange = false;  //设置响应标识为不响应
            this.Text = ConvertToPasswordChar(Text.Length);  //将输入的字符替换为密码字符
            IsResponseChange = true;   //回复响应标识
            this.SelectionStart = lastOffset + 1; //设置光标索引
            //Console.WriteLine(string.Format("SelectionStar:{0}", this.SelectionStart));
        }
        /// <summary>
        /// 按照指定的长度生成密码字符
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        private string ConvertToPasswordChar(int length)
        {
            if (PasswordBuilder != null)
                PasswordBuilder.Clear();
            else
                PasswordBuilder = new StringBuilder();
            for (var i = 0; i < length; i++)
                PasswordBuilder.Append(PasswordChar);
            return PasswordBuilder.ToString();
        }
        //6.如果用户设置了记住密码,密码文(PasswordStr)一开始就有值的话,别忘了在Load事件里事先替换一次明文
        private void ExTextBox_Loaded(object sender, RoutedEventArgs e)
        {
            if (IsPasswordBox)
            {
                IsResponseChange = false;
                this.Text = ConvertToPasswordChar(PasswordStr.Length);
                IsResponseChange = true;
            }
        }
        private bool IsResponseChange = true;
        private StringBuilder PasswordBuilder;
        private int lastOffset = 0;
    }
外部调用示例代码
<StackPanel VerticalAlignment="Center" >
	<TextBlock Text="水印密码输入框" FontSize="25" TextAlignment="Center"/>
	<local:ExTextBox Height="40" BorderCornerRadius="5" Margin="10,10" Background="White"
					 IsPasswordBox="False" PasswordStr="{Binding Password}" FontSize="20"/>
	<local:ExTextBox Height="40" BorderCornerRadius="5" Margin="10,10" Background="White" WaterRemark="普通水印文本框"
					 IsPasswordBox="True" PasswordStr="{Binding Password}" FontSize="20"/>
	<!--水印文本框-->
	<local:ExTextBox Height="40" BorderCornerRadius="5" Margin="10,10" Background="White" WaterRemark="带删除普通水印文本框"
					 IsPasswordBox="False" PasswordStr="{Binding Password}" FontSize="20"
					  OperateImage="Pack://application:,,,/ExPasswordBox;component/Images/delete.png"/>
	<!--水印密码框-->
	<local:ExTextBox  Height="40" BorderCornerRadius="5" Margin="10,10" Background="LightBlue" WaterRemark="密码输入框"
					  BorderBrush="Red" FontSize="20" ImageSize="32"
					  TipImage="Pack://application:,,,/ExPasswordBox;component/Images/man.png"
					  OperateImage="Pack://application:,,,/ExPasswordBox;component/Images/delete.png"
					  />
</StackPanel>
效果图:


WPF 带水印的密码输入框实现的更多相关文章
- WPF 带水印的密码输入框
		
原文:WPF 带水印的密码输入框 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/BYH371256/article/details/83652540 ...
 - WPF 带CheckBox、图标的TreeView
		
WPF 带CheckBox.图标的TreeView 在WPF实际项目开发的时候,经常会用到带CheckBox的TreeView,虽然微软在WPF的TreeView中没有提供该功能,但是微软在WPF中提 ...
 - WPF 带清除按钮的文字框SearchTextBox
		
原文:WPF 带清除按钮的文字框SearchTextBox 基于TextBox的带清除按钮的搜索框 样式部分: <!--带清除按钮文字框--> <Style TargetType=& ...
 - WPF 带刻度的滑动条实现
		
原文:WPF 带刻度的滑动条实现 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/BYH371256/article/details/83507170 ...
 - WPf 带滚动条WrapPanel 自动换行 和控件右键菜单
		
原文:WPf 带滚动条WrapPanel 自动换行 和控件右键菜单 技能点包括 WPf 样式的引用 数据的验证和绑定 比较适合初学者 前台: <Window.Resources> < ...
 - WPF 自定义TextBox带水印控件,可设置圆角
		
一.简单设置水印TextBox控件,废话不多说看代码: <TextBox TextWrapping="Wrap" Margin="10" Height=& ...
 - WPF中带水印的Textbox
		
很多时候我们都希望通过水印来告诉用户这里该填什么样格式的数据,那么我们就希望有这样的一个控件. 为了方便起见,先定义一个依赖属性专门来存放水印中显示的字符串. public sealed class ...
 - [WPF]带下拉列表的文本框
		
控件我已经弄好了,代码比较多,所以没办法全面介绍. 一开始我是直接继承Selector类来实现,做是做出来了,不过发现性能不太好.于是,我就想着自己来实现.毕竟我是做给自己用的,也不考虑过多的东西,也 ...
 - WPF自学入门(六)WPF带标题的内容控件简单介绍
		
在WPF自学入门(二)WPF-XAML布局控件的文章中分别介绍StackPanel,WarpPanel,DockPanel,Grid,Canvas五种布局容器的使用,可以让我们大致了解容器可以使用在什 ...
 
随机推荐
- xgcom  linux下的串口助手
			
好用到爆@@! 2.Install: Source code: http://code.google.com/p/xgcom/ svn checkout http://xgcom.googlecode ...
 - 6、Python文件操作工具 openpyxl 工具
			
#-*- coding:utf-8 -* from openpyxl.reader.excel import load_workbook import MySQLdb import time ...
 - 原生js模仿jq  fadeIn  fadeOut效果 兼容IE低版本
			
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
 - IDEA 常用插件收藏
			
1.maven helper 查看maven依赖,解决jar包冲突. 2.Alibaba Java Coding Guidelines 代码风格遵循阿里java规范. 3.Lombok 简化实体中的 ...
 - BZOJ 1041 圆上的整点 数学
			
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1041 题目大意:求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整 ...
 - Unable to perform unmarshalling at line number 16 and column 63 in RESOURCE hibernate.cfg.xml. Message: cvc-elt.1: 找不到元素 'hibernate-configuration' 的声明。
			
七月 02, 2017 4:32:37 下午 org.hibernate.Version logVersionINFO: HHH000412: Hibernate Core {5.2.10.Final ...
 - webpack中使用babel处理es6语法
			
index.js const arr = [ new Promise(()=>{}), new Promise(()=>{}) ]; arr.map(item => { consol ...
 - map详解<一>
			
首先了解下pair工具类: 这个类在头文件<utility>,功能:将俩个类型可能不一样的值组合在一起.,通过first和second来访问这两个值.还定义了operator == 和op ...
 - ERDAS IMAGINE 2014 32位 破解安装
			
1. 安装Install ERDAS Foundation 2014 2. 安装ERDAS IMAGINE 2014 32位 3. 安装Intergraph ...
 - scrapy---setting的字段含义
			
# -*- coding: utf-8 -*- # Scrapy settings for lizi project # # For simplicity, this file contains on ...