2009-07-08 10 views
16

Hi people stackoverflow. Sto lavorando con MVVM, ho ViewModel chiama UserViewModel con una password di proprietà. Nella vista è disponibile una password di controllo.PasswordBox con MVVM

<PasswordBox x:Name="txtPassword" Password="{Binding Password}" /> 

Ma questo xaml non funziona. Come si fa il legame ?? Aiuto per favore!!

+0

Si è verificato che il datacontext della finestra sia impostato sul modello di vista. Devi pubblicare un po 'di codice in modo che possiamo capire il tuo problema. –

+0

DataContext va bene. altre proprietà funzionano bene, ma con PasswordBox non posso. – Rangel

risposta

13

Per motivi di sicurezza, la proprietà Password non è una proprietà di dipendenza e pertanto non è possibile associarvi. Purtroppo è necessario eseguire l'associazione nel codice dietro alla vecchia maniera (registrarsi per l'evento OnPropertyChanged e aggiornare il valore con il codice ...)


ho rapida ricerca mi porta a this blog post che mostra come scrivi una proprietà allegata per eludere il problema. Se questo vale la pena o meno, dipende in realtà dalla tua avversione al code-behind.

5

È sempre possibile scrivere un controllo che include la password e aggiunge una proprietà di dipendenza per la proprietà Password.

Vorrei solo usare codice dietro, ma se si deve si può fare qualcosa di simile:

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

} 
+0

Io uso una soluzione simile ma trovo utile registrare DependencyProperty con FrameworkPropertyMetadata.BindsTwoWayByDefault in modo da non doverlo dichiarare ogni volta in XAML. –

+0

Capisco che questo è piuttosto vecchio, tuttavia se uso questo metodo rimuove la possibilità di impostare FontSize e ContentAlignment. Come faccio a evitare questo? –

0

controllare un altro thread sulla casella Password. È meglio non mantenere la password su qualsiasi DP o proprietà pubblica.

Other thread on passwordbox

2

C'è un problema con il BindablePasswordBox. Funziona solo in una direzione, PasswordBox in PasswordProperty. Di seguito è una versione modificata di esso che funziona in entrambe le direzioni. Registra un PropertyChangedCallback e aggiorna la password di PasswordBox quando viene chiamata. Spero che qualcuno lo trovi utile.

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

Per evitare di avere la password disponibile in memoria come testo normale in qualsiasi punto, fornisco il valore come parametro al mio 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> 

Quindi a mio modo di vedere il modello.

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

Mentre sarebbe opportuno fornire la SecurePassword direttamente dalla vincolante, sembra sempre di fornire un valore vuoto. Quindi questo NON funziona:

<Button Margin="0 0 8 0" MinWidth="65" 
      Command="{Binding LoginAccept}" 
      CommandParameter="{Binding ElementName=PasswordBox, Path=SecurePassword}"> 
+0

Ho sperimentato la stessa identica cosa! sai perché 'SecurePassword direttamente dall'associazione' non funziona? – Athafoud

+1

Non ho idea oltre a ciò che esiste una restrizione intenzionale per quel tipo specifico.SecurePassword non è una proprietà Dependency che probabilmente contribuisce al problema ma è una proprietà standard di sola lettura. Ma si potrebbe pensare che si possa ancora passarlo come parametro se non altro piuttosto che passare l'intero controllo. –