2009-05-20 13 views
10

Ich beginne gerade mit M-V-VM und WPF und habe Probleme, einige Bindungsprobleme zu verstehen.PasswordBox Binding

Ich habe eine Login-Seite, die eine ComboBox und eine PasswordBox hat. Die ComboBox sieht wie folgt aus:

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

Das funktioniert ganz gut - meine Werte erhalten aktualisiert jedes Mal die SelectedItem Änderungen an der ComboBox!

In meinem Viewmodel Ich habe ein ICommand, die dieses Verfahren verwendet, um zu bestimmen, ob die Login-Button aktiv ist:

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

Also mein Problem ist, ich habe nicht die PasswordBox an die Passwort-Eigenschaft gebunden auf dem Ansichtsmodell - Ich kann also nicht sagen, wann es aktualisiert wird. Wie kann ich den Wert PasswordBox zu meinem ViewModel bekommen? Alles, was ich gerade gelesen habe, sagt aus Sicherheitsgründen kein PasswordBox binden. Ich würde einfach die Passwortbeschränkung von CanLogin() entfernen, aber ich brauche den Wert, der an einen AccountService weitergegeben wird.

+0

Wenn Sie das Kennwort als Zeichenfolge (und nicht als SecureString) binden, legen Sie das Kennwort im Arbeitsspeicher Ihres Prozesses offen. Beide Lösungen gefährden die Sicherheit – Rubinsh

Antwort

27

Interessant.

schauen Sie sich diesen Blogbeitrag an und sehen Sie, ob er Ihnen hilft. http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html

Anscheinend ist der Link tot jetzt so hier ist die ursprüngliche Lösung (gefunden here):

Sie können angefügten Eigenschaften verwenden, um einen Helfer wie diese zu erstellen:

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

Verwendung:

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

Ich weiß, das ist eine wirklich alte Antwort und funktioniert, aber hat jemand bemerkt, wie verrückt der Code ist? Vielleicht sollte ich eine weniger komplizierte Version davon veröffentlichen? –

+1

Der obige Code funktioniert nicht (PasswordHelper), verwenden Sie stattdessen die Methode in der Verknüpfung (PasswordBoxAssistant). http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html – morph85

8

gab ich eine GIST here, die eine bindungsfähige Passwort-Box ist.

+1

Schöne Lösung. Irgendwelche Tipps, wie man die Eigenschaften der eingebetteten PasswordBox leicht erhöht (z. B. Vordergrund, Hintergrund), so dass sie in XAML zugänglich sind? –