2009-07-08 5 views
16

Hallo Leute stackoverflow. Ich arbeite mit MVVM, ich habe ViewModel Aufruf UserViewModel mit einem Eigenschaftskennwort. In der View haben Sie eine Kontrolle PasswordBox.PasswordBox mit MVVM

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

Aber diese XAML funktionieren nicht. Wie machst du die Bindung? Hilfe bitte!!

+0

Haben Sie sichergestellt, dass der Datenkontext des Fensters auf das Ansichtsmodell festgelegt ist. Sie müssen etwas mehr Code posten, damit wir Ihr Problem verstehen können. –

+0

DataContext ist in Ordnung. Andere Eigenschaften funktionieren gut, aber mit PasswordBox kann ich nicht. – Rangel

Antwort

13

Aus Sicherheitsgründen ist die Password-Eigenschaft keine Abhängigkeitseigenschaft und daher können Sie nicht an sie gebunden werden. Leider müssen Sie die Bindung in den Code hinter der alten Art und Weise (Register für OnPropertyChanged Ereignis und aktualisieren Sie den Wert durch den Code ...)


ich eine schnelle Suche bringt mich zu this blog post auszuführen, die zeigt, wie man Schreiben Sie eine angehängte Eigenschaft, um das Problem zu umgehen. Ob es sich lohnt oder nicht, hängt jedoch von Ihrer Abneigung gegen Code-Behind ab.

5

Sie können immer ein Steuerelement schreiben, das das Kennwort umschließt und eine Abhängigkeitseigenschaft für die Password-Eigenschaft hinzufügt.

Ich würde nur hinter verwenden Code, aber wenn Sie müssen Sie so etwas wie tun:

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

Ich verwende eine ähnliche Lösung, aber ich finde es nützlich, die DependencyProperty mit FrameworkPropertyMetadata.BindsTwoWayByDefault zu registrieren, so dass Sie es nicht jedes Mal im XAML deklarieren müssen. –

+0

Ich verstehe, dass dies ziemlich alt ist, aber wenn ich diese Methode verwende, wird die Möglichkeit zur Einstellung von FontSize und ContentAlignment entfernt. Wie komme ich hier zurecht? –

0

prüfen ein anderer Thread auf Feld Kennwort. Es ist besser, das Passwort nicht auf einer DP oder öffentlichen Eigenschaft zu halten.

Other thread on passwordbox

2

Es gibt ein Problem mit dem BindablePasswordBox. Es funktioniert nur in einer Richtung, PasswordBox zu PasswordProperty. Unten ist eine modifizierte Version davon, die in beide Richtungen funktioniert. Es registriert ein PropertyChangedCallback und aktualisiert das PasswordBox-Passwort, wenn es aufgerufen wird. Ich hoffe, dass jemand das nützlich findet.

1

Um zu vermeiden, dass das Kennwort als Klartext an irgendeiner Stelle im Speicher verfügbar ist, stelle ich den Wert als Parameter für meinen Befehl zur Verfügung.

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

Dann aus meiner Sicht Modell.

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

Während es Sinn machen würde, die SecurePassword direkt von der Bindung zu schaffen, scheint es immer einen leeren Wert zu liefern. So funktioniert das nicht:

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

Ich habe genau dasselbe erlebt! Weißt du, warum 'SecurePassword direkt von der Bindung' nicht funktioniert? – Athafoud

+1

Ich habe keine Ahnung, außer dass es eine absichtliche Beschränkung für diesen speziellen Typ gibt.SecurePassword ist keine DependencyProperty, die wahrscheinlich zu dem Problem beiträgt, aber eine schreibgeschützte Standardeigenschaft ist. Aber man könnte denken, man könnte es immer noch als Parameter übergeben, wenn nichts anderes als die gesamte Kontrolle übergibt. –