537mfb
537mfb

Reputation: 1482

Setting initial value of PasswordBox

I'm wondering if this is at all possible with all the security involved with the PasswordBox control:

I have a XAML form (C#/WPF) where users will configure a database access. In that form i'm using a PasswordBox to get the SQL Server user password.

Since this data is saved to disk for future use (in a pasword protected SQL Server CE database file), while on first run there is no password set, if the user comes back and needs to edit the SQL connection for some reason, then there could be a password kept from the previous configuration (unless he used Windows Authentication rather than SQL User Authentication)

So I want to show an empty PasswordBox on the first run but if there's a password set already, when the user returns I want to show X number of '*' (to give indication that there is a password in place.

Since PasswordBox.Password isn't bindable, I can only choose to always show it empty or always show a fixed number of '*' (by setting a default Password that doesn't actually represent the real password).

Is there any alternative (besides something like the PasswordBox Helper that injects binding of course - i'd rather not go that path as there might be a reason i haven't considered for MS to choose not to make it bindable even to a SecureString)?

Upvotes: 5

Views: 9368

Answers (2)

Mohit S
Mohit S

Reputation: 14044

You can read the Password from the file.

//Storing the Password in String.
string pwd = "Password Read from the file";
PasswordBox.Password = pwd;

So when the application is open for the first time and there would not be any password in the file it would show the empty PasswordBox. And again when the password has already been set by the user the Password will be found in the file and it would get loaded in the PasswordBox.

Upvotes: 5

daniel
daniel

Reputation: 1070

You can have this behavior for PasswordBox to enable binding in MVVM.

PasswordBoxBehavior.cs

public class PasswordBoxBehavior : Behavior<PasswordBox>
{
    public bool ResetPassword
    {
        get { return (bool)GetValue(ResetPasswordProperty); }
        set { SetValue(ResetPasswordProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ResetPassword.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ResetPasswordProperty =
        DependencyProperty.Register("ResetPassword", typeof(bool), typeof(PasswordBoxBehavior), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnResetPasswordChanged));

    static void OnResetPasswordChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        PasswordBoxBehavior behavior = depObj as PasswordBoxBehavior;
        PasswordBox item = behavior.AssociatedObject as PasswordBox;
        if (item == null)
            return;

        if ((bool)e.NewValue)
            item.Password = string.Empty;

        behavior.ResetPassword = false;
    }

    private bool isRoutedEventHandlerAssign;
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(PasswordBoxBehavior), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextChanged));

    static void OnTextChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        PasswordBoxBehavior behavior = depObj as PasswordBoxBehavior;
        PasswordBox item = behavior.AssociatedObject as PasswordBox;
        if (item == null)
            return;

        if (item.Password != e.NewValue as string)
        {
            item.Password = e.NewValue as string;
        }

        if (!behavior.isRoutedEventHandlerAssign)
        {
            item.PasswordChanged += (sender, eArg) =>
            {
                behavior.Text = item.Password;
            };
            behavior.isRoutedEventHandlerAssign = true;
        }
    }

    public PasswordBoxBehavior()
    {
    }
}

Use

<PasswordBox>
    <i:Interaction.Behaviors>
        <bh:PasswordBoxBehavior 
            Text="{Binding UserPassword}"
            ResetPassword="{Binding IsResetPassword}" />
    </i:Interaction.Behaviors>
</PasswordBox>

where

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:bh="clr-namespace:<some namespace>;assembly=<some assembly>"

Upvotes: 1

Related Questions