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

WPF文本框需求:输入字符显示半秒后转为*掩码

WPF 文本框实现“输入字符显示半秒后转为*”的方案

直接基于你已有的自定义TextBox逻辑,通过真实内容存储+DispatcherTimer延迟替换的方式实现需求,以下是完整的可运行代码:

自定义DelayedPasswordTextBox实现

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace YourAppNamespace.Controls
{
    public class DelayedPasswordTextBox : TextBox
    {
        // 存储用户输入的真实机密内容
        private string _realContent = string.Empty;
        // 延迟替换字符的定时器(WPF UI线程专用)
        private readonly DispatcherTimer _maskTimer;
        // 记录最后一次输入的位置,保证光标始终在末尾
        private int _lastInputPos;

        public DelayedPasswordTextBox()
        {
            // 初始化定时器,设置半秒延迟
            _maskTimer = new DispatcherTimer
            {
                Interval = TimeSpan.FromMilliseconds(500)
            };
            _maskTimer.Tick += OnMaskTimerTick;

            // 优化UI体验:隐藏只读光标、禁止文本选中
            IsReadOnlyCaretVisible = false;
            IsReadOnly = false;
        }

        protected override void OnTextInput(TextCompositionEventArgs e)
        {
            // 停止之前的定时器,避免连续输入时多次触发替换
            _maskTimer.Stop();

            // 追加真实输入内容
            _realContent += e.Text;
            // 更新显示:前面所有字符用*,最后一个显示输入的原字符
            Text = new string('*', _realContent.Length - 1) + e.Text;
            // 定位光标到末尾
            _lastInputPos = Text.Length;
            CaretIndex = _lastInputPos;

            // 启动定时器,半秒后替换最后一个字符为*
            _maskTimer.Start();

            // 阻止默认文本输入逻辑,避免原字符直接写入TextBox的Text属性
            e.Handled = true;
        }

        private void OnMaskTimerTick(object sender, EventArgs e)
        {
            _maskTimer.Stop();
            // 替换所有显示字符为*
            if (!string.IsNullOrEmpty(_realContent))
            {
                Text = new string('*', _realContent.Length);
                CaretIndex = Text.Length;
            }
        }

        // 处理退格键,保证真实内容和显示同步
        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            if (e.Key == Key.Back && _realContent.Length > 0)
            {
                _maskTimer.Stop();
                // 删除真实内容的最后一位
                _realContent = _realContent.Substring(0, _realContent.Length - 1);
                // 更新显示文本
                Text = new string('*', _realContent.Length);
                CaretIndex = Text.Length;
                e.Handled = true;
            }
            base.OnPreviewKeyDown(e);
        }

        // 对外提供获取真实机密内容的方法
        public string GetRealContent()
        {
            return _realContent;
        }

        // 可选:添加模式切换依赖属性,支持普通文本/延迟密码模式切换
        public static readonly DependencyProperty IsPasswordModeProperty =
            DependencyProperty.Register(nameof(IsPasswordMode), typeof(bool), typeof(DelayedPasswordTextBox),
                new PropertyMetadata(true, OnIsPasswordModeChanged));

        public bool IsPasswordMode
        {
            get => (bool)GetValue(IsPasswordModeProperty);
            set => SetValue(IsPasswordModeProperty, value);
        }

        private static void OnIsPasswordModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var textBox = (DelayedPasswordTextBox)d;
            if (!(bool)e.NewValue)
            {
                // 切换为普通模式:显示真实内容
                textBox._maskTimer.Stop();
                textBox.Text = textBox._realContent;
            }
            else
            {
                // 切换为密码模式:恢复掩码显示
                textBox.Text = new string('*', textBox._realContent.Length);
            }
        }
    }
}

XAML中使用自定义控件

  1. 先添加命名空间引用(替换成你的控件实际命名空间):
xmlns:controls="clr-namespace:YourAppNamespace.Controls"
  1. 直接使用控件:
<controls:DelayedPasswordTextBox Width="250" Height="35" />
  1. 切换模式示例(比如通过CheckBox控制):
<StackPanel>
    <controls:DelayedPasswordTextBox x:Name="SecretTextBox" Width="250" Height="35" />
    <CheckBox Content="切换为普通文本模式" 
              IsChecked="{Binding IsPasswordMode, ElementName=SecretTextBox, Mode=TwoWay}"
              Margin="0,10,0,0"/>
</StackPanel>

关键注意事项

  • 所有真实输入内容都存在_realContent字段中,通过GetRealContent()方法获取,不要直接用TextBox的Text属性
  • 使用DispatcherTimer而非普通Timer,避免WPF跨线程操作UI的异常
  • 额外处理了退格键逻辑,保证用户删除操作时显示和真实内容一致
  • 可选的IsPasswordMode依赖属性,直接支持你需要的“特定条件切换密码模式”需求

内容的提问来源于stack exchange,提问作者Praneeth Kumar Gunda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 00:45:52