I have a UWP application which uses a PasswordBox control for obscured text entry. The valid characters for the password varies by instance, and is known by the ViewModel layer at runtime. I want to be able to filter invalid characters as the user types them. What is the proper way to do that?
We have similar requirements for regular TextBox controls. We have been able to perform this kind of filtering for text boxes using the TextChanging event and the SelectionStart property for resetting the cursor position. But the PasswordBox does not have either of these.
The XAML for the password box looks like this
<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}" />
We then respond to the Password.set by checking the validity of the input, and if invalid, resetting to the prior value
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");
}
}
The call to SetCurrentValue() simply stores the entered password into our Model layer and should not be of consequence to this discussion. The call to _passwordControl.SetPassword updates the Password field on ThePasswordBox:
public void SetPassword(string password)
{
ThePasswordBox.Password = password;
}
HandlePasswordChange() forces other UI elements to re-evaluate, including an OK button that is disabling when the control is invalid. It's implementation should not be important to this question.
The problem with this approach is that when we reset the contents of the PasswordBox (the call to SetPassword, which sets PasswordBox.Password property) the cursor jumps to the first position. So for a numeric password, typing "12a4" would yield "412".
What are our options here?
What's the proper way to filter characters in a UWP PasswordBox?
From your code, you need not call SetPassword
method in Password.set
, it will make the cursor back the the start position. the better way is bind Password
within two way mode. And check the if Password is available. If the Password
contains unallowable character then call BackSpace with 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"
/>