WPF自定义控件--模拟手机密码输入控件,在输入时显示最后一个输入密码字符

using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace PasswordTest
{
    /// <summary>
    /// 显示最后一个字符的密码输入框
    /// </summary>
    public class BlinkPasswordBox : TextBox
    {
        #region DependencyProperty

        public static readonly DependencyProperty PasswordCharProperty = DependencyProperty.RegisterAttached("PasswordChar", typeof(char), typeof(BlinkPasswordBox), new FrameworkPropertyMetadata('●'));

        /// <summary>
        /// 密文字符
        /// </summary>
        public char PasswordChar
        {
            get { return (char)GetValue(PasswordCharProperty); }
            set { SetValue(PasswordCharProperty, value); }
        }

        public static readonly DependencyProperty PasswordProperty = DependencyProperty.RegisterAttached("Password", typeof(string), typeof(BlinkPasswordBox), new UIPropertyMetadata(""));
        /// <summary>
        /// 密码字符
        /// </summary>
        public string Password
        {
            get { return (string)GetValue(PasswordProperty); }
            set { SetValue(PasswordProperty, value); }
        }
        #endregion

        #region Properties
        /// <summary>
        /// 最后的光标位置
        /// </summary>
        private int mLastStart = 0;
        /// <summary>
        /// 明文消失的时间
        /// </summary>
        private int mDelay = 1000;
        /// <summary>
        /// 定时Token
        /// </summary>
        private CancellationTokenSource mWaitToken = new CancellationTokenSource();
        /// <summary>
        /// 密码
        /// </summary>
        private string mPassword = string.Empty;
        /// <summary>
        /// 正在更新文本
        /// </summary>
        private bool IsUpdating;
        /// <summary>
        /// 显示的文本
        /// </summary>
        private string ShowText
        {
            get { return base.Text; }
            set
            {
                IsUpdating = true;
                base.Text = value;
                IsUpdating = false;
            }
        }
        /// <summary>
        /// 密码设置
        /// </summary>
        public new string Text
        {
            get { return mPassword; }
            set
            {
                mPassword = value;
                this.ShowText = new string(PasswordChar, value.Length);
            }
        }
        #endregion
        #region protected override
        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            if (IsUpdating == true)
                return;

            string currentText = this.ShowText;
            int start = this.SelectionStart;

            RemoveChar(currentText, start);

            SetShowText(currentText, start);

            base.OnTextChanged(e);
        }
        /// <summary>
        /// 设置要显示的文本
        /// </summary>
        /// <param name="e"></param>
        /// <param name="currentText"></param>
        /// <param name="start"></param>
        private void SetShowText(string currentText, int start)
        {
            if (!string.IsNullOrEmpty(currentText))
            {
                string addChar = string.Empty;
                for (int i = 0; i < currentText.Length; i++)
                {
                    if (currentText[i] != PasswordChar)
                    {
                        addChar = currentText[i].ToString();
                        if (this.ShowText.Length == mPassword.Length)
                        {
                            // 修改字符
                            mPassword = mPassword.Remove(i, 1).Insert(i, currentText[i].ToString());
                        }
                        else
                        {
                            // 增加字符
                            mPassword = mPassword.Insert(i, currentText[i].ToString());

                        }
                    }
                }
                Password = mPassword;
                this.ShowText = new string(PasswordChar, mPassword.Length);
                if (!string.IsNullOrEmpty(addChar) && start > 0)
                {
                    ShowText = ShowText.Remove(start - 1, 1).Insert(start - 1, addChar);
                    WaitChange();
                }
                this.SelectionStart = start;
            }
        }
        /// <summary>
        /// 删除字符
        /// </summary>
        /// <param name="currentText"></param>
        /// <param name="start"></param>
        private void RemoveChar(string currentText, int start)
        {
            if (currentText.Length < mPassword.Length)
            {
                mPassword = mPassword.Remove(start, mPassword.Length - currentText.Length);
                Password = mPassword;
            }
        }

        #endregion

        #region Private Methods
        /// <summary>
        /// 等待明文自动隐藏
        /// </summary>
        private async void WaitChange()
        {
            try
            {
                mWaitToken.Cancel();
                mWaitToken = new System.Threading.CancellationTokenSource();
                await Task.Delay(mDelay, mWaitToken.Token);
                mLastStart = this.SelectionStart;
                this.ShowText = new string(PasswordChar, mPassword.Length);
                this.SelectionStart = mLastStart;
            }
            catch
            {

            }
        }
        #endregion
    }
}

  

posted @ 2020-08-26 10:34  wangjinming  阅读(302)  评论(0编辑  收藏  举报