wpf - PasswordBox con MVVM
passwordbox wpf (5)
Compruebe otro hilo en el cuadro de contraseña. Es mejor no guardar la contraseña en ningún DP o propiedad pública.
Hola gente stackoverflow. Estoy trabajando con MVVM, he hecho que ViewModel llame a UserViewModel con una contraseña de propiedad. En la vista tiene un control PasswordBox.
<PasswordBox x:Name="txtPassword" Password="{Binding Password}" />
Pero este xaml no funciona. ¿Cómo haces el enlace? ¡¡Ayuda por favor!!
Hay un problema con el BindablePasswordBox. Solo funciona en una dirección, PasswordBox a PasswordProperty. A continuación se muestra una versión modificada de la misma que funciona en ambas direcciones. Registra un PropertyChangedCallback y actualiza la contraseña de PasswordBox cuando se le llama. Espero que alguien encuentre esto útil.
public class BindablePasswordBox : Decorator
{
public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register("Password", typeof(string), typeof(BindablePasswordBox), new PropertyMetadata(string.Empty, OnDependencyPropertyChanged));
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
private static void OnDependencyPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
BindablePasswordBox p = source as BindablePasswordBox;
if (p != null)
{
if (e.Property == PasswordProperty)
{
var pb = p.Child as PasswordBox;
if (pb != null)
{
if (pb.Password != p.Password)
pb.Password = p.Password;
}
}
}
}
public BindablePasswordBox()
{
Child = new PasswordBox();
((PasswordBox)Child).PasswordChanged += BindablePasswordBox_PasswordChanged;
}
void BindablePasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
Password = ((PasswordBox)Child).Password;
}
}
Para evitar tener la contraseña disponible en la memoria como texto sin formato en cualquier punto, proporciono el valor como parámetro a mi comando.
<Label>User Name</Label>
<TextBox Text="{Binding UserName}" />
<Label>Password</Label>
<PasswordBox Name="PasswordBox" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 16 0 0">
<Button Margin="0 0 8 0" MinWidth="65"
Command="{Binding LoginAccept}"
CommandParameter="{Binding ElementName=PasswordBox}">
Login
</Button>
<Button MinWidth="65" Command="{Binding LoginCancel}">Cancel</Button>
</StackPanel>
Luego en mi modelo de vista.
public DelegateCommand<object> LoginAccept { get; private set; }
public DelegateCommand<object> LoginCancel { get; private set; }
public LoginViewModel {
LoginAccept = new DelegateCommand<object>(o => OnLogin(o), (o) => IsLoginVisible);
LoginCancel = new DelegateCommand<object>(o => OnLoginCancel(), (o) => IsLoginVisible);
}
private void OnLogin(object o)
{
var passwordBox = (o as System.Windows.Controls.PasswordBox);
var password = passwordBox.SecurePassword.Copy();
passwordBox.Clear();
ShowLogin = false;
var credential = new System.Net.NetworkCredential(UserName, password);
}
private void OnLoginCancel()
{
ShowLogin = false;
}
Si bien tendría sentido proporcionar SecurePassword directamente desde el enlace, siempre parece proporcionar un valor vacío. Así que esto NO funciona:
<Button Margin="0 0 8 0" MinWidth="65"
Command="{Binding LoginAccept}"
CommandParameter="{Binding ElementName=PasswordBox, Path=SecurePassword}">
Por razones de seguridad, la propiedad Contraseña no es una propiedad de dependencia y, por lo tanto, no puede vincularla. Desafortunadamente, deberá realizar el enlace en el código detrás de la forma antigua (regístrese para el evento OnPropertyChanged y actualice el valor a través del código ...)
La búsqueda rápida me lleva a esta publicación del blog que muestra cómo escribir una propiedad adjunta para evitar el problema. Si esto vale la pena o no, aunque realmente depende de su aversión al código subyacente.
Siempre puede escribir un control que ajuste la Contraseña y agregue una propiedad de dependencia para la propiedad Contraseña.
Solo usaría el código que está detrás, pero si debes, puedes hacer algo como:
public class BindablePasswordBox : Decorator
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(string), typeof(BindablePasswordBox));
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public BindablePasswordBox()
{
Child = new PasswordBox();
((PasswordBox)Child).PasswordChanged += BindablePasswordBox_PasswordChanged;
}
void BindablePasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
Password = ((PasswordBox)Child).Password;
}
}