You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

可切换显示/隐藏且支持自定义掩码字符的密码输入框最优方案咨询

最优实现方案:自定义单一TextBox控件

直接基于TextBox封装自定义控件,自行处理密码存储、掩码显示与明文切换逻辑,无需依赖特殊字体或双控件同步,完美满足需求。

方案优势

  • 单控件实现,彻底避免双控件(TextBox+PasswordBox)的状态同步问题
  • 支持任意自定义掩码字符,无需提前准备特殊字体
  • 直接通过字符串类型的Password属性处理密码,适配无安全要求的场景
  • 完整覆盖输入、退格、删除、粘贴等操作,光标位置保持正确,用户体验流畅

自定义PasswordTextBox控件代码(WPF场景)

public class PasswordTextBox : TextBox
{
    // 真实密码字符串属性
    public static readonly DependencyProperty PasswordProperty =
        DependencyProperty.Register(nameof(Password), typeof(string), typeof(PasswordTextBox), new PropertyMetadata(string.Empty));

    // 自定义掩码字符属性
    public static readonly DependencyProperty PasswordCharProperty =
        DependencyProperty.Register(nameof(PasswordChar), typeof(char), typeof(PasswordTextBox), new PropertyMetadata('●', OnPasswordCharChanged));

    // 密码显示/隐藏切换属性
    public static readonly DependencyProperty IsPasswordVisibleProperty =
        DependencyProperty.Register(nameof(IsPasswordVisible), typeof(bool), typeof(PasswordTextBox), new PropertyMetadata(false, OnIsPasswordVisibleChanged));

    public string Password
    {
        get => (string)GetValue(PasswordProperty);
        set => SetValue(PasswordProperty, value);
    }

    public char PasswordChar
    {
        get => (char)GetValue(PasswordCharProperty);
        set => SetValue(PasswordCharProperty, value);
    }

    public bool IsPasswordVisible
    {
        get => (bool)GetValue(IsPasswordVisibleProperty);
        set => SetValue(IsPasswordVisibleProperty, value);
    }

    // 掩码字符变更时更新显示
    private static void OnPasswordCharChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is PasswordTextBox ptb && !ptb.IsPasswordVisible)
        {
            ptb.UpdateDisplayText();
        }
    }

    // 显示状态变更时更新显示
    private static void OnIsPasswordVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is PasswordTextBox ptb)
        {
            ptb.UpdateDisplayText();
        }
    }

    // 处理普通文本输入
    protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
    {
        e.Handled = true;
        var newPassword = Password.Insert(SelectionStart, e.Text);
        Password = newPassword;
        UpdateDisplayText();
        SelectionStart = SelectionStart + e.Text.Length;
    }

    // 处理退格、删除键
    protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
    {
        base.OnPreviewKeyDown(e);
        if (e.Key == System.Windows.Input.Key.Back)
        {
            e.Handled = true;
            if (SelectionStart > 0)
            {
                Password = SelectionLength > 0 
                    ? Password.Remove(SelectionStart, SelectionLength) 
                    : Password.Remove(SelectionStart - 1, 1);
                UpdateDisplayText();
                SelectionStart = Math.Max(0, SelectionStart - (SelectionLength > 0 ? 0 : 1));
            }
        }
        else if (e.Key == System.Windows.Input.Key.Delete)
        {
            e.Handled = true;
            if (SelectionLength > 0)
            {
                Password = Password.Remove(SelectionStart, SelectionLength);
            }
            else if (SelectionStart < Password.Length)
            {
                Password = Password.Remove(SelectionStart, 1);
            }
            UpdateDisplayText();
        }
    }

    // 处理粘贴操作
    protected override void OnPasting(System.Windows.DataObjectPastingEventArgs e)
    {
        e.CancelCommand();
        if (e.DataObject.GetDataPresent(typeof(string)))
        {
            var pastedText = (string)e.DataObject.GetData(typeof(string));
            var newPassword = Password.Insert(SelectionStart, pastedText);
            Password = newPassword;
            UpdateDisplayText();
            SelectionStart = SelectionStart + pastedText.Length;
        }
    }

    // 更新控件显示文本(明文/掩码)
    private void UpdateDisplayText()
    {
        Text = IsPasswordVisible ? Password : new string(PasswordChar, Password.Length);
    }
}

XAML使用示例

<Window x:Class="PasswordDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:PasswordDemo"
        Title="Password Input Demo" Height="150" Width="300">
    <StackPanel VerticalAlignment="Center">
        <local:PasswordTextBox x:Name="customPwdBox" 
                               PasswordChar="*" 
                               Width="220" 
                               Margin="10"
                               FontSize="14"/>
        <CheckBox Content="显示密码" 
                  IsChecked="{Binding ElementName=customPwdBox, Path=IsPasswordVisible}"
                  Margin="10"
                  HorizontalAlignment="Center"/>
    </StackPanel>
</Window>

方案说明

  • 真实密码存储在Password属性中,完全以字符串形式处理,适配无安全要求的场景
  • 通过PasswordChar属性可设置任意自定义掩码字符(如*、#、●等)
  • IsPasswordVisible属性绑定CheckBox,一键切换明文/掩码显示
  • 拦截所有常见输入操作,确保显示文本与真实密码同步,光标位置始终正确

内容的提问来源于stack exchange,提问作者EldHasp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 03:17:02