I have a login view with a PasswordBox
marked up as follows:
<PasswordBox x:Name="PasswordText" Width="Auto" Margin="5" PasswordChanged="PasswordTextOnPasswordChanged" />
The problem with it is that the caret remains at the extreme left of its text box; it doesn't move forward as you type, so the last character you type ends up the first character in the text box. E.g. when I type the password "123", the content of the PasswordBox
, after conversion to a normal string, is "321". It is not the conversion code, for if I pre-populate the control with a password, i.e. no typing involved, its content converts to the correct plain string.
What is going on here? It seems buggy to me that the caret doesn't follow ones typing.
Behind the scenes (i.e. code-behind) I have:
private void PasswordTextOnPasswordChanged(object sender, RoutedEventArgs e)
{
if (!_suppressPasswordChanged)
{
((LoginFormViewModel)DataContext).Password = PasswordText.SecurePassword;
}
}
_suppressPasswordChanged
is just to avoid triggering the PasswordTextOnPasswordChanged
handler when I explicitly set the password.
public void SetPassword(string password)
{
try
{
_suppressPasswordChanged = true;
PasswordText.Password = password;
}
finally
{
_suppressPasswordChanged = false;
}
}
A
PasswordBox
has no data binding, and thus requires code in the view to update the view-model when the user types in that box. I originally had this event handler:Then I wanted to be able to set the
Password
property in the view-model, and had to add this view method:Called from the setter:
This ended up with
SetPassword
triggeringPasswordTextOnPasswordChanged
, which called the setter again, as it should normally, but not when recursively triggered by code. My first and embarrassing attempt at preventing these methods calling each other was:but because
SetPassword
always resetsuppressPasswordChanged
in itsfinally
, it would still always get called fromPasswordTextOnPasswordChanged
.My current, working, but maybe slightly smelly, solution is to move the responsibility of setting the 'do-not-call' flag to the event handler:
Now,
SetPassword
is only ever called from the setter in the view-model, and then setting the caret to the beginning of the text is ideal.