How can I make a TextBox be a “password box” and d

2019-02-11 10:19发布

问题:

How can I do this in XAML:

PSEUDO-CODE:

<TextBox Text="{Binding Password}" Type="Password"/>

so that the user sees stars or dots when he is typing in the password.

I've tried various examples which suggest PasswordChar and PasswordBox but can't get these to work.

e.g. I can do this as shown here:

<PasswordBox Grid.Column="1" Grid.Row="1"
    PasswordChar="*"/>

but I of course want to bind the Text property to my ViewModel so I can send the value the bound TextBox when the button is clicked (not working with code behind), I want to do this:

<TextBox Grid.Column="1" Grid.Row="0" 
    Text="{Binding Login}" 
    Style="{StaticResource FormTextBox}"/>
<PasswordBox Grid.Column="1" Grid.Row="1"
    Text="{Binding Password}" 
    PasswordChar="*"
    Style="{StaticResource FormTextBox}"/>

But PasswordBox doesn't have a Text property.

回答1:

To get or set the Password in a PasswordBox, use the Password property. Such as

string password = PasswordBox.Password;

This doesn't support Databinding as far as I know, so you'd have to set the value in the codebehind, and update it accordingly.



回答2:

Send the passwordbox control as a parameter to your login command.

<Button Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=PasswordBox}"...>

Then you can call CType(parameter, PasswordBox).Password in your viewmodel.



回答3:

There's a way to bind on a PasswordBox here: PasswordBox Databinding



回答4:

Thanks Cody, that was very helpful. I've just added an example for guys using the Delegate Command in C#

<PasswordBox x:Name="PasswordBox"
             Grid.Row="1" Grid.Column="1"
             HorizontalAlignment="Left" 
             Width="300" Height="25"
             Margin="6,7,0,7" />
<Button Content="Login"
        Grid.Row="4" Grid.Column="1"
        Style="{StaticResource StandardButton}"
        Command="{Binding LoginCommand}"
        CommandParameter="{Binding ElementName=PasswordBox}"
        Height="31" Width="92"
        Margin="5,9,0,0" />

 

public ICommand LoginCommand
{
   get
   {
        return new DelegateCommand<object>((args) =>
        {
            // Get Password as Binding not supported for control-type PasswordBox
            LoginPassword = ((PasswordBox) args).Password;

            // Rest of code here
        });
   }
}


回答5:

You can make your TextBox as customed PasswordBox by simply adding the following value to FontFamily property of your TextBox control.

<TextBox
    Text="{Binding Password}"
    FontFamily="ms-appx:///Assets/PassDot.ttf#PassDot"
    FontSize="35"/>

In my case this works perfectly. This will show dot in place of the actual text (not star(*) though).



回答6:

I did the below from the Views codebehind to set my property within the view model. Not sure if it really " breaks" the MVVM pattern but its the best and least complexe solution found.

  var data = this.DataContext as DBSelectionViewModel;

        data.PassKey = txtPassKey.Password;


回答7:

The problem with using the PasswordBox is that it is not very MVVM friendly due to the fact that it works with SecureString and therefore requires a shim to bind it to a String. You also cannot use the clipboard. While all these things are there for a reason, you may not require that level of security. Here is an alternative approach that works with the clipboard, nothing fancy. You make the TextBox text and background transparent and bind the text to a TextBlock underneath it. This textblock converts characters to * using the converter specified.

<Window.Resources>
    <local:TextToPasswordCharConverter x:Key="TextToPasswordCharConverter" />
</Window.Resources>

<Grid Width="200">
    <TextBlock Margin="5,0,0,0" Text="{Binding Text, Converter={StaticResource TextToPasswordCharConverter}, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" FontFamily="Consolas" VerticalAlignment="Center" />
    <TextBox Foreground="Transparent" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" FontFamily="Consolas" Background="Transparent" />
</Grid>

And here is the Value Converter:

class TextToPasswordCharConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return new String('*', value?.ToString().Length ?? 0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Make sure your Text property on your viewmodel implements INotifyPropertyChanged