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
[...] WPF NavigationService blanks PasswordBox.Password, which breaks the MVVM PasswordHelper Category: MVVM, WPF | Comment (RSS) | Trackback [...]
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
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