WPF NavigationService blanks PasswordBox.Password, which breaks the MVVM PasswordHelper

I am using three things that are just not friends:

  • Pages and NavigationService
  • Model-View-ViewModel design
  • The PasswordBox control

Problem 1 – PasswordBox.Password is not a DependencyProperty

First off, Model-View-ViewModel is design centered around data binding. But PasswordBox.Password is not a DependencyProperty and therefore does not support binding. That is ok, a PasswordBoxAssistant (alternately I have seen it named PasswordHelper or PasswordBoxHelper) as described originally here and also here fixes seems to fix this.

That is, it fixes it unless you are using the NavigationService.

Problem 2 – NavigationService blanks PasswordBox.Password

See when the NavigationService navigates to another page, it somehow know that the current page has a PasswordBox and if it finds a PasswordBox, it blanks the password out.  So since we are using PasswordBoxHelper to make MVVM and data binding work, the value is blanked in the ViewModel and Model as well.

For now, I happen to be using a custom button for navigation so I can simply do this in my ViewModel:

String tempPw = MyPassword;
NavigationService.Navigate(NewPage);
MyPassword = tempPw;

However, this is not the best solution. What if there were multiple links and different ways to navigate?

I think the best solution would be to figure out how to make PasswordBoxAssistant handle this. But I am not sure how or if there is anyway to tell that the password was blanked by the NavigationService and to ignore binding in this instance.

Resource:
http://social.msdn.microsoft.com/Forums/en/wpf/thread/d91aec90-1476-41c0-a925-7661745094c5

3 Comments

  1. [...] WPF NavigationService blanks PasswordBox.Password, which breaks the MVVM PasswordHelper Category: MVVM, WPF  |  Comment (RSS)  |  Trackback [...]

  2. Jay Kidd says:

    You can check the stack to see if its a navigation caused update trying to blank the password and prevent that...

    Example:
    Public Shared Sub SetPassword(ByVal dp As DependencyObject, ByVal value As String)

    ' check the stack to find out if its a navigation update
    ' the nagivation will blank passwords to prevent passwords from being journaled.
    If value = "" Then
    Dim st As StackTrace = New StackTrace()
    Dim sf As StackFrame = st.GetFrame(1)
    Dim Source As String = ""
    For Each sf In st.GetFrames
    If sf.GetMethod.Name = "OnNavigating" Then
    ' we are navigating, so don't perform the update
    Exit Sub
    End If
    Next
    End If

    ' update the value, this is a normal update
    dp.SetValue(PasswordProperty, value)

    End Sub

    • Jay Kidd says:

      Oh and you can also refresh the page with the password box in it if someone navigates back to it. If you don't refresh the page, then the password will stay blank, but in memory it will be correctly set.
      This is exampled here... i'm sure 1 solution out of many...

      ' constructor
      Public Sub New()

      ' This call is required by the designer.
      InitializeComponent()

      End Sub

      ' add a reference to refresh the page when someone navigates back to it
      Private Sub ServerListPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

      ' handle refreshing the page when someone clicks back
      AddHandler NavigationService.LoadCompleted, AddressOf RefreshPageOnBack

      End Sub

      ' rebuild the page, otherwise the password boxes will be blank
      Private Sub RefreshPageOnBack()
      Try
      NavigationService.Navigate(New ServerListPage)
      Catch ex As Exception
      End Try
      End Sub

Leave a Reply

How to post code in comments?