2009-05-20 24 views
10

Sono appena iniziato con M-V-VM e WPF e ho problemi a comprendere alcuni problemi vincolanti.PasswordBox Binding

Ho una pagina di accesso che ha un ComboBox e un PasswordBox. Il ComboBox assomiglia a questo:

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

Questo funziona bene - i miei valori vengono aggiornati ogni volta che il SelectedItem modifiche sul ComboBox!

Nel mio ViewModel ho un ICommand che utilizza questo metodo per determinare se il pulsante Login è attiva:

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

Quindi il mio problema è che non ho la PasswordBox legata alla proprietà Password sul ViewModel - Quindi non ho modo di dire quando è aggiornato.

Quindi, come posso ottenere il valore di PasswordBox sul mio ViewModel? Tutto quello che ho appena letto dice che non si associa un PasswordBox per motivi di sicurezza. Vorrei semplicemente togliere la restrizione della password sul CanLogin() ma ho bisogno che il valore passi ad un AccountService.

+0

Se si esegue il binding della password come stringa (e non SecureString), si espone la password nella memoria del processo. Entrambe le soluzioni fornite compromettono la sicurezza – Rubinsh

risposta

27

Interessante.

guarda questo post del blog e vedi se ti sta aiutando. http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html

A quanto pare il link è morto ora ecco la soluzione originale (che si trova here):

È possibile utilizzare proprietà associate per creare un aiuto come questo:

 
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); 
    } 
} 

Usalo:

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

So che questa è una risposta molto vecchia e funziona, ma qualcuno ha notato quanto sia stravagante il codice? Forse dovrei pubblicare una versione meno complicata di questo? –

+1

Il codice sopra non funziona (PasswordHelper), utilizzare invece il metodo nel collegamento (PasswordBoxAssistant). http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html – morph85

8

Ho inserito un GIST here che è una casella di password associabile.

+1

Soluzione piacevole. Qualche suggerimento su come elevare facilmente le proprietà (ad esempio Primo piano, Sfondo) della PasswordBox incorporata in modo che possano essere accessibili in XAML? –