Binding Passwords

Those who’ve been following my blog and conversations with the WPF Disciples know that I love the databinding power of WPF, and in almost all cases I’m a very happy bunny. There is one stain in the awe inspiring goodness that is bound applications, and that’s the PasswordBox. Superficially, this control looks like a textbox, but there is a problem when you write MVVM applications and rely on binding the way I do; you can’t bind to it. Yes, you heard it right, you can’t bind with a PasswordBox.

There’s a good reason for this lack of binding – PasswordBox.Password is not a Dependency Property, ostensibly because this would result in the password being stored in clear text in memory, which is a potential security concern. If, however, you aren’t too worried about this potential security breach, there is a workround. Good news, folks – the following class (taken from my forthcoming Twitter client Songbird) is a way to perform binding with the PasswordBox.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;

namespace SongBird.Infrastructure
{
    /// <summary>
    /// This class adds binding capabilities to the standard WPF PasswordBox.
    /// </summary>
    public class BoundPasswordBox
    {
        #region BoundPassword
        private static bool _updating = false;

        /// <summary>
        /// BoundPassword Attached Dependency Property
        /// </summary>
        public static readonly DependencyProperty BoundPasswordProperty =
            DependencyProperty.RegisterAttached("BoundPassword", 
                typeof(string), 
                typeof(BoundPasswordBox),
                new FrameworkPropertyMetadata(string.Empty, OnBoundPasswordChanged));

        /// <summary>
        /// Gets the BoundPassword property.
        /// </summary>
        public static string GetBoundPassword(DependencyObject d)
        {
            return (string)d.GetValue(BoundPasswordProperty);
        }

        /// <summary>
        /// Sets the BoundPassword property.
        /// </summary>
        public static void SetBoundPassword(DependencyObject d, string value)
        {
            d.SetValue(BoundPasswordProperty, value);
        }

        /// <summary>
        /// Handles changes to the BoundPassword property.
        /// </summary>
        private static void OnBoundPasswordChanged(
            DependencyObject d, 
            DependencyPropertyChangedEventArgs e)
        {
            PasswordBox password = d as PasswordBox;
            if (password != null)
            {
                // Disconnect the handler while we're updating.
                password.PasswordChanged -= PasswordChanged;
            }

            if (e.NewValue != null)
            {
                if (!_updating)
                {
                    password.Password = e.NewValue.ToString();
                }
            }
            else
            {
                password.Password = string.Empty;
            }
            // Now, reconnect the handler.
            password.PasswordChanged += new RoutedEventHandler(PasswordChanged);
        }

        /// <summary>
        /// Handles the password change event.
        /// </summary>
        static void PasswordChanged(object sender, RoutedEventArgs e)
        {
            PasswordBox password = sender as PasswordBox;
            _updating = true;
            SetBoundPassword(password, password.Password);
            _updating = false;
        }

        #endregion

    }
}

Using it couldn’t be simpler, just add a reference to the namespace in your XAML, and update your PasswordBox with the BoundPasswordBox class. You’ve now got a bindable PasswordBox.

<PasswordBox
    Grid.Column="1"
    Grid.Row="2"
    Margin="5,5,5,5"
    password:BoundPasswordBox.BoundPassword="{Binding Path=Password,
        Mode=TwoWay, 
        UpdateSourceTrigger=PropertyChanged}" 
    VerticalAlignment="Center"/>
Advertisements

5 thoughts on “Binding Passwords

  1. Thanks for the very useful post!

    This enabled me to setup a proper validation rule for the PasswordBox control (without the bindable property, this was not possible).

    I am including some code below for someone else that might use your concept together with validation.

    <PasswordBox Name="PasswordBoxPassword" MaxLength="14" Grid.Column="1" Grid.Row="4">
    <password:BoundPasswordBox.BoundPassword>
    <Binding Path="Password" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
    <Binding.ValidationRules>
    <validator:MandatoryRule></validator:MandatoryRule>
    </Binding.ValidationRules>
    </Binding>
    </password:BoundPasswordBox.BoundPassword>
    </PasswordBox>

    Thanks!

    – Nalin J

  2. Mike L

    Very cool! It took me a few hacks to get the namespace declaration right in my XAML, but it’s working great now. Thanks!

    -Mike L

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s