2009-05-20 16 views
10

Po prostu zaczynam od M-V-VM i WPF i mam problemy ze zrozumieniem niektórych wiążących się problemów.Wiązanie PasswordBox

Mam stronę logowania, która ma ComboBox i PasswordBox. ComboBox wygląda następująco:

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

Działa to dobrze - moje wartości aktualizowane za każdym razem SelectedItem zmiany na ComboBox!

W moim ViewModel Mam ICommand który wykorzystuje tę metodę w celu ustalenia, czy przycisk jest aktywny Login:

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

Więc mój problem jest nie mieć PasswordBox związany z właściwością hasło na ViewModel - więc nie mam sposobu, aby powiedzieć, kiedy jest aktualizowany.

Jak więc uzyskać wartość PasswordBox dla mojego ViewModel? Wszystko, co przeczytałem po prostu mówi, nie wiąże się ze względów bezpieczeństwa PasswordBox. Po prostu zdejmę ograniczenie hasła na CanLogin(), ale potrzebuję tej wartości, aby przekazać ją do usługi AccountService.

+0

Jeśli wiążisz hasło jako ciąg (a nie SecureString), ujawniasz hasło w pamięci procesu. Oba rozwiązania kompromitują bezpieczeństwo – Rubinsh

Odpowiedz

27

Interesujące.

spójrz na ten wpis na blogu i sprawdź, czy ci to pomaga. http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html

Widocznie link jest martwy teraz tak tu jest oryginalnym rozwiązaniem (znaleziono here):

Można użyć dołączonych właściwości do stworzenia pomocnika takiego:

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

Użyj go:

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

Wiem, że jest to naprawdę stara odpowiedź i działa, ale czy ktoś zauważył, jak zwariowany jest kod? Może powinienem opublikować mniej skomplikowaną wersję tego? –

+1

Powyższy kod nie działa (PasswordHelper), należy zamiast tego użyć metody w odnośniku (PasswordBoxAssistant). http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html – morph85

8

Wysłałem GIST here, który jest wiążącym polem hasła.

+1

Dobre rozwiązanie. Wszelkie wskazówki dotyczące łatwego podnoszenia właściwości (np. Pierwszego planu, tła) wbudowanego PasswordBox, aby można było uzyskać do nich dostęp w XAML? –