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五种布局容器的使用,可以让我们大致了解容器可以使用在什 ...
随机推荐
- PHP笔记09:PHP之 MVC理解
1. 首先通俗地说说我对MVC的理解: Model是负责干活的,它干的活主要是从数据库中获取需要的数据以及对获取的数据按照业务逻辑进行加工处理,至于为什么要干某件活,何时干某件活它一概不管,而这正是C ...
- window用ssh连接本机虚拟机中的ubuntu
@window用ssh连接本机虚拟机中的ubuntu 主机和虚拟机间通信,需将2台机器的IP地址设为同一网段. 1.设置虚拟机: 虚拟机–> 设置–> Hardware –> Net ...
- How Flask Routing Works
@How Flask Routing Works The entire idea of Flask (and the underlying Werkzeug library) is to map UR ...
- luogu P1262 间谍网络
嘟嘟嘟 建图还是很明显的. 接着分两种情况: 1.图中不存在环:那么只要收买那些入度为0的点.如果这些点有的不能收买.就不能控制所有间谍. 2.图中存在环,那么对于这些在环中的点,我们只要收买数额最少 ...
- git编译安装报错 http-push.c:20:19: 警告:expat.h:没有那个文件或目录
解决: [root@hdoop3 git-2.18.1]# yum install expat-devel
- JDK(二)JDK1.8源码分析【排序】timsort
如无特殊说明,文中的代码均是JDK 1.8版本. 在JDK集合框架中描述过,JDK存储一组Object的集合框架是Collection.而针对Collection框架的一组操作集合体是Collecti ...
- keepalived 的进程/usr/sbin/keepalived -D 只有2个
操作系统:openSUSE 11.3 (x86_64) /usr/sbin/keepalived -D 只有2条 日志:ls /var/log/messages* -lrth Can't init ...
- 1<=portNo<=4竟然在keil4.71里面不报错
1.if( 1<=portNo<=4 ) { CardIn2_CS_L; //pull low CardIn1_CS_H; CardOut1_CS_H; CardOut2_CS_H ...
- 解决Js跨域访问的问题
1,最近有个需求,用Js获取Html标签<input type="file"/>的路径!遇到代码拒绝访问,提示安全验证,不允许跨域访问,简单的设置一下浏览器即可,不过对 ...
- Oracle 安全性一
创建和管理数据库用户账户 用户账户属性 用户账户拥有很多在创建账户时定义的属性.这些属性将应用于连接到账户的会话,在会话运行期间,DBA或会话可以更改其中一些属性. 用户名 身份验证方法 默认表空间 ...