Access PasswordBox in MVVM environment
A 'Binding' cannot be set on the 'Password' property of type 'PasswordBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject
The reason the Password property is not done DependencyProperty is due to security concerns. If it were possible to bind the property to PasswordBox, then it would be stored in memory in the clear, and this is not a good idea from the point of view of Microsoft. Therefore, the password in PasswordBox is encrypted and decrypted when the Password property is called.
I have found several solutions to this problem. There are ways that preserve the principles of MVVM, but create the problem described above. If the requirements do not provide for this kind of security, then you can
Create a simple controller:
To get the password, we need an interface:
public interface IPasswordSupplier
{
string GetPassword();
}
We inherit the control from this interface and return the password value in the function:
public partial class LoginControl : UserControl, IPasswordSupplier
{
public LoginControl()
{
InitializeComponent();
}
public string GetPassword()
{
return pwdBox.Password;
}
}
An unpleasant feature of the method is that LoginControl will have to be created in the code, because You need to get IPasswordSupplier. Using the IoC container, register the instance of the control in App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
IUnityContainer container = new UnityContainer();
LoginControl loginControl = new LoginControl();
container.RegisterInstance(loginControl);
LoginViewModel loginViewModel = new LoginViewModel(container);
loginControl.DataContext = loginViewModel;
MainWindow mainWindow = new MainWindow(loginControl);
MainWindowViewModel windowViewModel = new MainWindowViewModel(loginViewModel);
mainWindow.DataContext = windowViewModel;
mainWindow.Show();
}
Now in the ViewModel of control we can access the Password property of the PasswordBox:
public string Password
{
get
{
IPasswordSupplier passwordSupplier = container.Resolve();
return passwordSupplier.GetPassword();
}
}
Thus, the Password property of our ViewModel does not store the value of the password, but receives it each time it is accessed from the PasswordBox, which in turn will decrypt it for us. Perhaps this violates MVVM, as Now our ViewModel is indirectly associated with View through this interface, but still this way seems to me the most suitable for solving the problem.