WPF TextBox模仿PasswordBox的密码显示功能(二)(升级版)

WPF TextBox模仿PasswordBox的密码显示功能(二)(升级版)WPFTextBox显示密码,模仿PasswordBox功能

大家好,又见面了,我是你们的朋友全栈君。

WPF TextBox模仿PasswordBox的密码显示功能(二)(升级版)

这并不是多此一举,因为WPF的PasswordBox不支持继承,所以想扩展PasswordBox的属性就没法实现,所以有了本文内容,当然这个思路也可以扩展到其他语言。

一、新建自定义控件
在这里插入图片描述二、下面是完整的类(这是创建了一个“自定义控件”)

using System.Windows;

namespace SuperControl
{ 
   
    /// <summary>
    /// SuperPasswordBoxPro
    /// </summary>
    public class SuperPasswordBoxPro : TextBox
    { 
   
        static SuperPasswordBoxPro()
        { 
   
            DefaultStyleKeyProperty.OverrideMetadata(typeof(SuperPasswordBoxPro), new FrameworkPropertyMetadata(typeof(STextBox)));
            //重写Text属性改变回调方法
            TextProperty.OverrideMetadata(typeof(SuperPasswordBoxPro), new FrameworkPropertyMetadata(new PropertyChangedCallback(TextChangedCallback)));
        }

        //Text属性改变回调方法
        private static void TextChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
   
            SuperPasswordBoxPro instance = (SuperPasswordBoxPro)d;
            //新的前端密码文本
            string text = e.NewValue.ToString();
            //已键入的文本长度
            int textLength = text.Length;
            //已保存的密码长度
            int psdLength = instance.Password.Length;
            //判断密码是否已修改
            if (textLength == psdLength && text == new string(instance.PasswordChar, text.Length)) return;
            //记住光标位置(设置完Text后会丢失,所以现在要记住)
            int selectionStart = instance.SelectionStart;
            //起始修改位置
            int startIndex = -1;
            for (int i = 0; i < textLength; i++)
            { 
   
                if (text[i] != instance.PasswordChar)
                { 
   
                    startIndex = i;
                    break;
                }
            }
            //结束修改位置
            int stopIndex = -1;
            for (int i = textLength - 1; i >= 0; i--)
            { 
   
                if (text[i] != instance.PasswordChar)
                { 
   
                    stopIndex = i;
                    break;
                }
            }
            //添加或修改了一个或连续的多个值
            if (startIndex != -1)
            { 
   
                //累计修改长度
                int alterLength = stopIndex - startIndex + 1;
                //长度没变化,单纯的修改了一个或连续的多个值
                if (textLength == psdLength)
                { 
   
                    instance.Password = instance.Password.Substring(0, startIndex) + text.Substring(startIndex, alterLength) + instance.Password.Substring(stopIndex + 1);
                }
                //新增了内容
                else
                { 
   
                    //新增且修改了原来内容
                    if (alterLength > textLength - psdLength)
                    { 
   
                        //计算未修改密码个数 textLength - alterLength
                        //计算已修改密码个数 = 原密码长度 - 未修改密码个数 psdLength - (textLength - alterLength)
                        //原密码该保留的后半部分的索引 = 已修改密码个数 + 起始修改位置
                        instance.Password = instance.Password.Substring(0, startIndex) + text.Substring(startIndex, alterLength) + instance.Password.Substring(psdLength - (textLength - alterLength) + startIndex);
                    }
                    //单纯的新增了一个或多个连续的值
                    else
                    { 
   
                        instance.Password = instance.Password.Substring(0, startIndex) + text.Substring(startIndex, alterLength) + instance.Password.Substring(startIndex);
                    }

                }
            }
            //删除了一个或连续的多个值
            else
            { 
   
                //已删除的数据长度 SelectionStart 为 TextBox 的属性(获取或设置当前所选内容的起始位置的字符索引)
                int length = psdLength - textLength;
                if (instance.SelectionStart < textLength)
                { 
   
                    //改变了中间的数据
                    instance.Password = instance.Password.Substring(0, instance.SelectionStart) + instance.Password.Substring(instance.SelectionStart + length);
                }
                else
                { 
   
                    //删除了结尾的数据
                    instance.Password = instance.Password.Substring(0, instance.SelectionStart);
                }
            }
            //设置光标位置
            instance.SelectionStart = selectionStart;
        }

        /// <summary>
        /// 密码
        /// </summary>
        public string Password
        { 
   
            get { 
    return (string)GetValue(PasswordProperty); }
            set { 
    SetValue(PasswordProperty, value); }
        }
        public static readonly DependencyProperty PasswordProperty =
            DependencyProperty.Register("Password", typeof(string), typeof(SuperPasswordBoxPro), new PropertyMetadata("", new PropertyChangedCallback(PasswordChangedCallback)));
        //Password属性改变回调方法
        private static void PasswordChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
   
            SuperPasswordBoxPro instance = (SuperPasswordBoxPro)d;
            instance.Text = new string(instance.PasswordChar, e.NewValue.ToString().Length);
        }

        /// <summary>
        /// 密码显示字符
        /// </summary>
        public char PasswordChar
        { 
   
            get { 
    return (char)GetValue(PasswordCharProperty); }
            set { 
    SetValue(PasswordCharProperty, value); }
        }
        public static readonly DependencyProperty PasswordCharProperty =
            DependencyProperty.Register("PasswordChar", typeof(char), typeof(SuperPasswordBoxPro), new PropertyMetadata('●'));
    }
}

三、如何使用
1、将命名空间改成你自己项目的,也就是nampspace和你项目保持一致
2、xaml里直接<local:SuperPasswordBoxPro />即可
3、Password属性才是真实的密码,请不要用Text属性
4、MVVM用到数据绑定的时候直接绑定Password属性即可

有问题欢迎留言,如果觉得有用请点个”赞”,谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/161499.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Delphi 2010 新增功能之: 手势编程[2] – 通过 OnGesture 识别手势

    Delphi 2010 新增功能之: 手势编程[2] – 通过 OnGesture 识别手势

    2021年8月31日
    75
  • 微信小程序 之 40029

    微信小程序 之 40029开发版正常使用,但是生成体验版之后报40029错误。错误原因:1:openid和当前小程序不对应,或者AppSecret秘钥和当前小程序不对应的。2:当前小程序能正确获取到token,但是在code还没有失效时,另一个小程序也用这个小程序的openid或者AppSecret秘钥去请求token。这个时候也会报40029,说到底还是第一个错误,只是触发的方式不同。解决办法也很简单,检查一下,当前的openid和AppSecret是否和当前要部署使用的小程序的openid和Ap..

    2022年5月6日
    46
  • 什么是债券久期[通俗易懂]

    什么是债券久期[通俗易懂]在做债券的投资分析中经常出现的一个词汇——债券久期,之前更多地是专注于开发,并不明白数字背后的业务含义,今天特意梳理下并做个记录。百度百科的解释:久期也称持续期,是1938年由F.R.Macaula

    2022年8月3日
    3
  • plsql 注册码「建议收藏」

    plsql 注册码「建议收藏」plsql下载地址https://www.allroundautomations.com/bodyplsqldevreg.html12.0.3.182164bit:注册码:ProductCode(产品编号):jtrexa75fat2mgcetfhx767laqrbtssqrkserialNumber(序列号):335566password:xs374ca12.0…

    2022年7月13日
    102
  • 关于Platform SDK和Windows SDK

    关于Platform SDK和Windows SDK原文地址:http://www.cnblogs.com/holynn/archive/2009/04/29/1446498.html问题1:什么是WindowsSDK?WindowsSDK是用来支持32位和64位Windows平台以及.NET框架编程模型的开发包。WindowsSDK这个名字从WindowsVista开始使用,它包含以前PlatformSDK中的所有内容,同时包含

    2022年5月4日
    42
  • Android:简单的弹幕效果达到

    Android:简单的弹幕效果达到

    2022年1月14日
    70

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号