At first we define an interface that contains just the SecureString Password as property.
public interface IHavePassword { System.Security.SecureString Password { get; } }
The View implements the IHavePassword interface. The Property Password in code-behind returns the SecurePassword of the PasswordBox.
public partial class LoginView : UserControl, IHavePassword { public LoginView() { InitializeComponent(); DataContext = new LoginViewModel(); } public System.Security.SecureString Password { get { return UserPassword.SecurePassword; } } }
In the XAML part of the View the click event of the login button is send by using the RelayCommand pattern that builds on WPF Commanding. Therefore the Command and the CommandParameter properties are set. The View is set to the CommandParameter.
<UserControl x:Class="MvvmPassword.LoginView" x:Name="This" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid> ... <PasswordBox x:Name="UserPassword" Grid.Row="2" Grid.Column="1" Margin="4" /> <Button x:Name="Login" Grid.Row="3" Grid.ColumnSpan="2" Margin="4" Content="Login" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=This}"/> ... </Grid> </UserControl>In the ViewModel the LoginCommand is linked to the Login method. This method gets the View as parameter. The view is casted to defined interface IHavePassword. From that we can easily obtain the secure password.
private void Login(object parameter) { var passwordContainer = parameter as IHavePassword; if (passwordContainer != null) { var secureString = passwordContainer.Password; PasswordInVM = ConvertToUnsecureString(secureString); } }The SecureString needs to be converted to string to validate the entered password. There are some pitfalls of converting a SecureString. A nice explanation of them can be found in How to properly convert SecureString to String by Fabio Pintos.
private string ConvertToUnsecureString(SecureString securePassword) { if (securePassword == null) { return string.Empty; } IntPtr unmanagedString = IntPtr.Zero; try { unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword); return Marshal.PtrToStringUni(unmanagedString); } finally { Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); } }
The source code can be downloaded from https://code.msdn.microsoft.com/Get-Password-from-df012a86?redir=0
Hmm it looks like yoour blog atte my first comment (it was super long) so
ReplyDeleteI guess I'll just sum it up what I wrote and say, I'm thoroughly enjoying your blog.
I too am an aspiriung blog writer buut I'm still new to everything.
Do you have any tips and hints for beginner blog writers?I'd really
appreciate it.
Please attach the full code link.
ReplyDeleteI don't understand completely. You say "In the ViewModel the LoginCommand is linked to the Login method." How does this link take place? If LoginCommand is a property within the ViewModel how can it receive a parameter?
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteAnswered my own question using a delegate
ReplyDeleteSomething like
public ICommand LoginCommand { get; private set; }
Then within the constructor
LoginCommand = new DelegateCommand < object > (Login);
Thanks chriga!
ReplyDeleteYou are welcome!
ReplyDeleteFor other readers, the question was: How does this link from LoginCommand to Login method take place?
The full code can be found here: https://code.msdn.microsoft.com/Get-Password-from-df012a86?redir=0