2009-05-20 7 views
10

Estoy empezando con M-V-VM y WPF y tengo problemas para entender algunos problemas vinculantes.Encuadernación con PasswordBox

Tengo una página de inicio de sesión que tiene un y un PasswordBox. El ComboBox se parece a esto:

<ComboBox Name="comboBox1" SelectedItem="{Binding Path=Username}"> 

Esto funciona muy bien - mis valores se actualizan cada vez que el SelectedItem cambios en la ComboBox!

En mi modelo de vista Tengo una ICommand que utiliza este método para determinar si el botón de inicio de sesión es activa:

public bool CanLogin() 
{ 
    return !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password); 
} 

Así que mi problema es que no tengo la PasswordBox unido a la propiedad Password en el modelo de vista - Así que no tengo forma de saber cuándo se actualiza.

Entonces, ¿cómo obtengo el valor de PasswordBox en mi ViewModel? Todo lo que he leído solo dice no enlazar un PasswordBox por razones de seguridad. Simplemente eliminaría la restricción de contraseña en CanLogin() pero necesito el valor para pasar a un AccountService.

+0

Si vincula la contraseña como cadena (y no como SecureString), está exponiendo la contraseña en la memoria de su proceso. Ambas soluciones dañan la seguridad – Rubinsh

Respuesta

27

Interesante.

mira esta publicación de blog y mira si te está ayudando. http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html

Al parecer, el enlace está muerto así que aquí es la solución original (que se encuentra here):

puede utilizar las propiedades unidas para crear un ayudante así:

 
public static class PasswordHelper 
{ 
    public static readonly DependencyProperty PasswordProperty = 
     DependencyProperty.RegisterAttached("Password", 
     typeof(string), typeof(PasswordHelper), 
     new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged)); 

    public static readonly DependencyProperty AttachProperty = 
     DependencyProperty.RegisterAttached("Attach", 
     typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false, Attach)); 

    private static readonly DependencyProperty IsUpdatingProperty = 
     DependencyProperty.RegisterAttached("IsUpdating", typeof(bool), 
     typeof(PasswordHelper)); 


    public static void SetAttach(DependencyObject dp, bool value) 
    { 
     dp.SetValue(AttachProperty, value); 
    } 

    public static bool GetAttach(DependencyObject dp) 
    { 
     return (bool)dp.GetValue(AttachProperty); 
    } 

    public static string GetPassword(DependencyObject dp) 
    { 
     return (string)dp.GetValue(PasswordProperty); 
    } 

    public static void SetPassword(DependencyObject dp, string value) 
    { 
     dp.SetValue(PasswordProperty, value); 
    } 

    private static bool GetIsUpdating(DependencyObject dp) 
    { 
     return (bool)dp.GetValue(IsUpdatingProperty); 
    } 

    private static void SetIsUpdating(DependencyObject dp, bool value) 
    { 
     dp.SetValue(IsUpdatingProperty, value); 
    } 

    private static void OnPasswordPropertyChanged(DependencyObject sender, 
     DependencyPropertyChangedEventArgs e) 
    { 
     PasswordBox passwordBox = sender as PasswordBox; 
     passwordBox.PasswordChanged -= PasswordChanged; 

     if (!(bool)GetIsUpdating(passwordBox)) 
     { 
      passwordBox.Password = (string)e.NewValue; 
     } 
     passwordBox.PasswordChanged += PasswordChanged; 
    } 

    private static void Attach(DependencyObject sender, 
     DependencyPropertyChangedEventArgs e) 
    { 
     PasswordBox passwordBox = sender as PasswordBox; 

     if (passwordBox == null) 
      return; 

     if ((bool)e.OldValue) 
     { 
      passwordBox.PasswordChanged -= PasswordChanged; 
     } 

     if ((bool)e.NewValue) 
     { 
      passwordBox.PasswordChanged += PasswordChanged; 
     } 
    } 

    private static void PasswordChanged(object sender, RoutedEventArgs e) 
    { 
     PasswordBox passwordBox = sender as PasswordBox; 
     SetIsUpdating(passwordBox, true); 
     SetPassword(passwordBox, passwordBox.Password); 
     SetIsUpdating(passwordBox, false); 
    } 
} 

usarlo:

<PasswordBox w:PasswordHelper.Attach="True" 
      w:PasswordHelper.Password="{Binding Text, ElementName=plain, Mode=TwoWay}" 
      Width="100"/> 
+0

Sé que esta es una respuesta muy antigua y funciona, pero ¿alguien notó lo raro que es el código? ¿Tal vez debería publicar una versión menos complicada? –

+1

El código anterior no funciona (PasswordHelper), use el método en el enlace (PasswordBoxAssistant). http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html – morph85

8

He publicado un GIST here que es un cuadro de contraseña vinculable.

+1

Buena solución. ¿Alguna sugerencia sobre cómo elevar fácilmente las propiedades (por ejemplo, primer plano, fondo) del PasswordBox incrustado para que se pueda acceder a ellas en XAML? –