首页 > 解决方案 > 在 UWP PasswordBox 中过滤字符的正确方法是什么?

问题描述

我有一个 UWP 应用程序,它使用 PasswordBox 控件进行模糊文本输入。密码的有效字符因实例而异,并且 ViewModel 层在运行时知道。我希望能够在用户键入无效字符时过滤它们。这样做的正确方法是什么?

我们对常规 TextBox 控件有类似的要求。我们已经能够使用 TextChanging 事件和用于重置光标位置的 SelectionStart 属性对文本框执行这种过滤。但是 PasswordBox 没有这些。

密码框的 XAML 如下所示

    <PasswordBox
        x:Name="ThePasswordBox"
        Grid.Row="1"
        MaxLength="{Binding MaxPasswordLength, Mode=OneTime}"
        IsEnabled="{Binding IsPasscodeEnabled, Mode=OneWay}"
        Password="{Binding Password, FallbackValue=1234, Mode=TwoWay}"
        PlaceholderText= "{Binding PlaceholderText, Mode=OneWay}" />

然后我们通过检查输入的有效性来响应 Password.set,如果无效,则重置为先前的值

        set
        {
            if (_password != value && value != null)
            {
                // verify that the new password would be valid; if not, roll back
                if (!IsPasswordContentAcceptable(value))
                {
                    _passcodeControl.SetPassword(_password);
                    return;
                }

                _password = value;

                // push the new password to the data binding
                _passcodeDataBinding.SetCurrentValue(_password);

                // update the UI
                HandlePasswordChange();

                OnPropertyChanged("Password");
            }
        }

对 SetCurrentValue() 的调用只是将输入的密码存储到我们的模型层中,不应该对本次讨论产生影响。对 _passwordControl.SetPassword 的调用会更新 ThePasswordBox 上的 Password 字段:

    public void SetPassword(string password)
    {
        ThePasswordBox.Password = password;
    }

HandlePasswordChange() 强制其他 UI 元素重新评估,包括在控件无效时禁用的 OK 按钮。它的实现对这个问题应该不重要。

这种方法的问题在于,当我们重置 PasswordBox 的内容(调用 SetPassword,设置 PasswordBox.Password 属性)时,光标会跳转到第一个位置。因此,对于数字密码,输入“12a4”将产生“412”。

我们在这里有什么选择?

标签: c#xamluwppasswordbox

解决方案


在 UWP PasswordBox 中过滤字符的正确方法是什么?

从您的代码中,您无需调用SetPasswordin 方法Password.set,它会使光标回到起始位置。更好的方法是Password在双向模式内绑定。并检查密码是否可用。如果Password包含不允许的字符,则 BackSpace使用 调用InputInjector

public string PassWord
{

    get { return _passWord; }
    set
    {
        if(value != null && IsPasswordContentAcceptable(value))
        {
            _passWord = value;
            OnPropertyChanged();
        }
        else
        {
            InputInjector inputInjector = InputInjector.TryCreate();
            var info = new InjectedInputKeyboardInfo();
            info.VirtualKey = (ushort)(VirtualKey.Back);
            inputInjector.InjectKeyboardInput(new[] { info });               
        }

    }
}

Xaml

<PasswordBox
    x:Name="ThePassWordBox"
    MaxLength="20"
    Password="{x:Bind PassWord, Mode=TwoWay}"      
    PlaceholderText="Input your Password"
    />

推荐阅读