Mark's Blog

.Net, C#, VB.Net, SQL, WPF, Silverlight, WCF, ASP.Net, EF

Thursday, June 9, 2011

WPF PasswordBox, MVVM, Data Binding, and VB.NET

I am currently working with a client that is writing a WPF application using VB.NET. One issue we ran into was that you cannot data bind to the password property of the PasswordBox since it is not a dependency property. I stumbled on the following article which details creating PasswordHelper class allowing data binding and keeping with the MVVM pattern. 

http://wpftutorial.net/PasswordBox.html

The example is written in C# so I had to port it to VB.NET for my project. Below is the VB.NET version of the PasswordHelper class. The XAML all works the same as the example.

Public NotInheritable Class PasswordHelper
    Private Sub New()
    End Sub
    Public Shared ReadOnly PasswordProperty As DependencyProperty = DependencyProperty.RegisterAttached("Password", GetType(String), GetType(PasswordHelper), New FrameworkPropertyMetadata(String.Empty, New PropertyChangedCallback(AddressOf OnPasswordPropertyChanged)))

    Public Shared ReadOnly AttachProperty As DependencyProperty = DependencyProperty.RegisterAttached("Attach", GetType(Boolean), GetType(PasswordHelper), New PropertyMetadata(False, New PropertyChangedCallback(AddressOf Attach)))

    Private Shared ReadOnly IsUpdatingProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsUpdating", GetType(Boolean), GetType(PasswordHelper))


    Public Shared Sub SetAttach(dp As DependencyObject, value As Boolean)
        dp.SetValue(AttachProperty, value)
    End Sub

    Public Shared Function GetAttach(dp As DependencyObject) As Boolean
        Return CBool(dp.GetValue(AttachProperty))
    End Function

    Public Shared Function GetPassword(dp As DependencyObject) As String
        Return DirectCast(dp.GetValue(PasswordProperty), String)
    End Function

    Public Shared Sub SetPassword(dp As DependencyObject, value As String)
        dp.SetValue(PasswordProperty, value)
    End Sub

    Private Shared Function GetIsUpdating(dp As DependencyObject) As Boolean
        Return CBool(dp.GetValue(IsUpdatingProperty))
    End Function

    Private Shared Sub SetIsUpdating(dp As DependencyObject, value As Boolean)
        dp.SetValue(IsUpdatingProperty, value)
    End Sub

    Private Shared Sub OnPasswordPropertyChanged(sender As System.Windows.DependencyObject, e As System.Windows.DependencyPropertyChangedEventArgs)
        Dim passwordBox As PasswordBox = TryCast(sender, PasswordBox)
        RemoveHandler passwordBox.PasswordChanged, AddressOf PasswordChanged

        If Not CBool(GetIsUpdating(passwordBox)) Then
            passwordBox.Password = DirectCast(e.NewValue, String)
        End If
        AddHandler passwordBox.PasswordChanged, AddressOf PasswordChanged
    End Sub

    Private Shared Sub Attach(sender As DependencyObject, e As DependencyPropertyChangedEventArgs)
        Dim passwordBox As PasswordBox = TryCast(sender, PasswordBox)

        If passwordBox Is Nothing Then
            Return
        End If

        If CBool(e.OldValue) Then
            RemoveHandler passwordBox.PasswordChanged, AddressOf PasswordChanged
        End If

        If CBool(e.NewValue) Then
            AddHandler passwordBox.PasswordChanged, AddressOf PasswordChanged
        End If
    End Sub

    Private Shared Sub PasswordChanged(sender As Object, e As RoutedEventArgs)
        Dim passwordBox As PasswordBox = TryCast(sender, PasswordBox)
        SetIsUpdating(passwordBox, True)
        SetPassword(passwordBox, passwordBox.Password)
        SetIsUpdating(passwordBox, False)
    End Sub
End Class

No comments:

Post a Comment