UWP 自定义密码框控件
1. 概述
微软官方有提供自己的密码控件,但是控件默认的行为是输入密码,会立即显示掩码,比如 *。如果像查看真实的文本,需要按查看按钮。
而我现在自定义的密码控件是先显示你输入的字符2s,然后再显示成掩码。当然这种场景并不一定适用于密码,也可以用在Pin码。
a. 微软官方的密码框

b. 自定义的效果

2. 密码框控件实现
要想实现自定义的密码框,我们当然要继承微软的TextBox控件,然后加入我们自己需要的东西。
a. 这里添加了一个加密类型的密码 Password 字段,真实密码文本 RealPassword 字段,一个Timer定时器来控制显示掩码
internal class CustomPasswordBox : TextBox
{
#region Member Variables
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(SecureString), typeof(CustomPasswordBox), new PropertyMetadata(new SecureString())); public static readonly DependencyProperty RealPasswordProperty =
DependencyProperty.Register("RealPassword", typeof(string), typeof(CustomPasswordBox), new PropertyMetadata(string.Empty)); private DispatcherTimer maskTimer;
#endregion
}
b. 公开控件属性字段
public SecureString Password
{
get
{
return (SecureString)GetValue(PasswordProperty);
} set
{
SetValue(PasswordProperty, value);
}
} public string RealPassword
{
get
{
return (string)GetValue(RealPasswordProperty);
} set
{
SetValue(RealPasswordProperty, value);
}
}
c. 然后再构造函数里添加一个需要相应的事件,还有初始化Timer
public CustomPasswordBox()
{
PreviewKeyDown += CustomPasswordBox_PreviewKeyDown;
CharacterReceived += CustomPasswordBox_CharacterReceived;
BeforeTextChanging += CustomPasswordBox_BeforeTextChanging;
SelectionChanged += CustomPasswordBox_SelectionChanged;
ContextMenuOpening += CustomPasswordBox_ContextMenuOpening;
TextCompositionStarted += CustomPasswordBox_TextCompositionStarted; maskTimer = new DispatcherTimer { Interval = new TimeSpan(, , ) };
maskTimer.Tick += MaskTimer_Tick;
}
在PreviewKeyDown、CharacterReceived、BeforeTextChanging这三个事件里,主要处理字符的输入删除等逻辑。
在SelectionChanged事件里,我们主要处理不让用户选中文本
在ContextMenuOpening,主要是屏蔽右键菜单,比如复制剪切粘贴
在TextCompositionStarted主要屏蔽中文等组合输入法
另外,在我的场景里面,我们只让用户输入数字,所以加入了数字验证,以及在Xbox上开启了InputScope=NumbericPin模式。
d. 添加事件响应代码
private void CustomPasswordBox_PreviewKeyDown(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e)
{
switch (e.OriginalKey)
{
case VirtualKey.Back:
case VirtualKey.Delete:
if (SelectionLength > )
{
RemoveFromSecureString(SelectionStart, SelectionLength);
}
else if (e.OriginalKey == VirtualKey.Delete && SelectionStart < Text.Length)
{
RemoveFromSecureString(SelectionStart, );
}
else if (e.OriginalKey == VirtualKey.Back && SelectionStart > )
{
int caretIndex = SelectionStart;
if (SelectionStart > && SelectionStart < Text.Length)
caretIndex = caretIndex - ;
RemoveFromSecureString(SelectionStart - , );
//SelectionStart = caretIndex;
} e.Handled = true;
break; default:
//e.Handled = true;
break;
}
} private void CustomPasswordBox_CharacterReceived(UIElement sender, Windows.UI.Xaml.Input.CharacterReceivedRoutedEventArgs args)
{
if (!char.IsDigit(args.Character))
return; AddToSecureString(args.Character.ToString());
args.Handled = true;
} private void CustomPasswordBox_BeforeTextChanging(TextBox sender, TextBoxBeforeTextChangingEventArgs args)
{
args.Cancel = args.NewText.Any(c => !char.IsDigit(c) && !char.ToString(c).ToString().Equals("●"));
//if (args.NewText.Replace("●", "") != "")
// AddToSecureString(args.NewText.Replace("●", ""));
} private void CustomPasswordBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
e.Handled = true;
} private void CustomPasswordBox_SelectionChanged(object sender, RoutedEventArgs e)
{
SelectionStart = Text.Length;
SelectionLength = ;
} private void CustomPasswordBox_TextCompositionStarted(TextBox sender, TextCompositionStartedEventArgs args)
{
return;
} private void MaskTimer_Tick(object sender, object e)
{
MaskAllDisplayText();
}
e. 实现Timer里面的2s后将字符串变成掩码
2s后看TextBox里面的字符数,然后设置对应长度的掩码
private void MaskAllDisplayText()
{
maskTimer.Stop();
int caretIndex = SelectionStart;
Text = new string('●', Text.Length);
SelectionStart = caretIndex;
}
f. 添加字符和删除字符
private void AddToSecureString(string text)
{
if (SelectionLength > )
{
RemoveFromSecureString(SelectionStart, SelectionLength);
} if (Password.Length >= || RealPassword.Length >= )
return;
foreach (char c in text)
{
System.Diagnostics.Debug.WriteLine(text);
int caretIndex = SelectionStart;
if (caretIndex - < )
Password.InsertAt(, c);
else
Password.InsertAt(caretIndex - , c);
RealPassword += c.ToString();
//MaskAllDisplayText();
if (caretIndex == Text.Length)
{
maskTimer.Stop();
maskTimer.Start();
//Text = Text.Insert(caretIndex++, c.ToString());
}
else
{
//Text = Text.Insert(caretIndex++, "●");
}
SelectionStart = Text.Length;
}
} private void RemoveFromSecureString(int startIndex, int trimLength)
{
int caretIndex = SelectionStart;
for (int i = ; i < trimLength; ++i)
{
Password.RemoveAt(startIndex);
RealPassword = RealPassword.Remove(startIndex, );
} Text = Text.Remove(startIndex, trimLength);
SelectionStart = caretIndex;
}
3. 控件使用方法
<local:CustomPasswordBox
InputScope="NumericPin"
MaxLength="" />
一个例子
<Grid>
<local:CustomPasswordBox
x:Name="PSW"
InputScope="NumericPin"
Padding="200 0 0 0"
Style="{StaticResource MyTextBox}"
Height="Auto"
MaxLength=""
CharacterSpacing=""
FontSize=""
VerticalAlignment="Top"/>
<TextBlock
x:Name="realPSW"
FontSize=""
Margin="0 200"
HorizontalAlignment="Center"
Text="{Binding ElementName=PSW, Path=RealPassword, Mode=OneWay}"/>
</Grid>
UWP 自定义密码框控件的更多相关文章
- wxpython 支持python语法高亮的自定义文本框控件的代码
在研发闲暇时间,把开发过程中比较重要的一些代码做个珍藏,下面的代码内容是关于wxpython 支持python语法高亮的自定义文本框控件的代码,应该是对大家也有用. import keywordimp ...
- [uwp]自定义图形裁切控件
开始之前,先上一张美图.图中的花叫什么,我已经忘了,或者说从来就不知道,总之谓之曰“野花”.只记得花很美,很香,春夏时节,漫山遍野全是她.这大概是七八年前的记忆了,不过她依旧会很准时的在山上沐浴春光, ...
- WPF登录功能,对于密码框的操作,其实WPF有个PasswordBox专门的密码框控件,完全可以选择自己要显示的密码符号。
在链接数据库后,点击登录时需要判断用户名和密码框是否为空,而PasswordBox不像textbox那样判断 textbox判断文本框为空 if (this.UserName.Text.Trim()= ...
- 示例:自定义WPF底层控件UI库 HeBianGu.General.WpfControlLib V2.0版本
原文:示例:自定义WPF底层控件UI库 HeBianGu.General.WpfControlLib V2.0版本 一.目的:封装了一些控件到自定义的控件库中,方便快速开发 二.实现功能: 基本实现常 ...
- Android 高仿微信支付密码输入控件
像微信支付密码控件,在app中是一个多么司空见惯的功能.最近,项目需要这个功能,于是乎就实现这个功能. 老样子,投篮需要找准角度,变成需要理清思路.对于这个"小而美"的控件,我们思 ...
- WPF自定义控件与样式(8)-ComboBox与自定义多选控件MultComboBox
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 下拉选 ...
- C# Winform 通过FlowLayoutPanel及自定义的编辑控件,实现快速构建C/S版的编辑表单页面
个人理解,开发应用程序的目的,不论是B/S或是C/S结构类型,无非就是实现可供用户进行查.增.改.删,其中查询用到最多,开发设计的场景也最为复杂,包括但不限于:表格记录查询.报表查询.导出文件查询等等 ...
- Winform 通过FlowLayoutPanel及自定义的编辑控件,实现快速构建C/S版的编辑表单页面 z
http://www.cnblogs.com/zuowj/p/4504130.html 不论是B/S或是C/S结构类型,无非就是实现可供用户进行查.增.改.删,其中查询用到最多,开发设计的场景 也最为 ...
- 在 Visual C++ 中开发自定义的绘图控件
本文讨论的重点介于两者 之间 — 公共控件赋予您想要的大部分功能,但控件的外观并不是您想要的.例如,列表视图控件提供在许多视图风格中显示数据列表的方式 — 小图标.大图标.列表和详细列表(报告).然而 ...
随机推荐
- Vue基础篇 (1) —— Vue-Router的使用
Vue-Cli中Vue-Router的使用 一.创建vue-cli的项目 npm create myproject vue create 为vue.js 3.0构建项目的命令,2.0版本可以通过vue ...
- 分享 HT 实用技巧:实现指南针和 3D 魔方导航
前言 三维场景时常需要一个导航标识,用来确定场景所处的方位. 一般有两种表现形式:指南针.小方盒(方位魔方). 参考一下百度百科中的 maya 界面,可以看到右上角有一个标识方位的小盒子,说的就是它: ...
- Dynamics CRM 365 不用按钮工具,直接用js脚本控制按钮的显示隐藏
Dynamics CRM 365 不用按钮工具,直接用js脚本控制按钮的显示隐藏: try { // 转备案按钮 let transferSpecialRequestButton = parent.p ...
- 多核CPU硬件架构介绍
转自:http://book.51cto.com/art/201004/197196.htm SISD.MIMD.SIMD.MISD计算机的体系结构 1. 计算平台介绍 Flynn于1972年提出了计 ...
- Netty 源码解析(八): 回到 Channel 的 register 操作
原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 今天是猿灯塔“365篇原创计划”第八篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源 ...
- h5页面自动播放视频、音频_关于媒体文件自动全屏播放的实现方式
在移动端(ios和android)播放视频的时候,我们即使定义了autoplay属性,仍然不能自动播放.这是由于手机浏览器为了防止浪费用户的网络流量,在默认情况下是不允许媒体文件自动播放的,除非用户自 ...
- gulp 如何排除文件和文件夹
在网上找了好久,很多用gulp-ignore来处理,或者!来处理 经验证,gulp-ignore没有效果,如果有大神路过,还请指教:!一般的写法只能排除单个文件,以下直接写结论 1.如何排除单个文件 ...
- 读CSAPP第一章的收获
这个系列只写了CSAPP第三版对于我的收获. 里面的内容很多,我只写我以前不知道的,然后现在又觉得挺有用的内容. 没有很好的排版,将就看. Amadhl定律:主要观点,想要显著加速整个系统,必须提升全 ...
- BUUCTF-Misc-No.2
比赛信息 比赛地址:Buuctf靶场 [GUET-CTF2019]虚假的压缩包 | SOLVED 解压文件夹,发现2个zip,第一个伪加密,破解后 n=33 e=3 m=0 while m<10 ...
- 02 flask源码剖析之flask快速使用
02 flask快速使用 目录 02 flask快速使用 1.flask与django的区别 2. 安装 3. 依赖wsgi Werkzeug 4. 快速使用flask 5. 用户登录&用户管 ...