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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 逻辑回归LR模型简介「建议收藏」

    逻辑回归LR模型简介「建议收藏」4.LR与线性回归的区别1.都是广义的线性回归,但LR可用于分类,在feature到结果的映射中加入了sigmoid(),实现了非线性。2.损失函数:线性回归–>平方损失函数;LR–>似然函数3.预测范围:线性回归–>整个实数域(敏感度一致);LR–>[0,1]…

    2022年10月13日
    3
  • J2EE架构师之路

    J2EE架构师之路不经意的回首,工作进入第五个年头了,发现走过了从Java程序员到J2EE架构师的历程。发现电脑上安装了各种各样的J2EE工具:JBuilder,WSAD,Eclipse,Rose,Together,Weblogic,Jtest,Optimizator,Mysql…发现电脑上保存了各种各样的OpenSource项目:Tomcat,JBoss,Ant,Hibernate,Spr

    2022年6月30日
    25
  • 内核态和用户态的区别_会导致用户进程用户态到内核态

    内核态和用户态的区别_会导致用户进程用户态到内核态1、用户态和内核态的区别?明白这两个概念之前,我们得知道用户空间和内核空间。用户空间:指的就是用户可以操作和访问的空间,这个空间通常存放我们用户自己写的数据等。内核空间:是系统内核来操作的一块空间,这块空间里面存放系统内核的函数、接口等。在用户空间下执行,我们把此时运行得程序的这种状态成为用户态,而当这段程序执行在内核的空间执行时,这种状态称为内核态。当一个任务(进程)执行系统…

    2022年9月18日
    2
  • SpringBoot 面试题及答案

    SpringBoot 面试题及答案文章目录1.什么是SpringBoot?2.SpringBoot有哪些优点?3.什么是JavaConfig?4.如何重新加载SpringBoot上的更改,而无需重新启动服务器?5.SpringBoot中的监视器是什么?6.如何在SpringBoot中禁用Actuator端点安全性?7.如何在自定义端口上运行SpringBoot应用程序?8.什么是YAML?9.如何实现SpringBoot应用程序的安全性?10.如何集成SpringBoot和Activ

    2022年5月21日
    43
  • 招聘 | 深圳市人工智能与机器人研究院AIRS 特种机器人研究中心

    招聘 | 深圳市人工智能与机器人研究院AIRS 特种机器人研究中心

    2020年11月14日
    220
  • 微生物生态排序分析——CCA分析

    微生物生态排序分析——CCA分析微生物生态排序分析 CCA 分析 library vegan library ggplot2 library permute library lattice sa4 read table spes csv header T row names 1 sep S8 p read table S8 p csv header T se

    2025年8月11日
    4

发表回复

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

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