2017-02-18 3 views
-1

J'écris l'application WPF MVVM Prism 6.2. Dans la vue de la fenêtre de connexion (c'est-à-dire PrismUserControl) j'ai une propriété liée à PaswordBox (via le comportement) à la propriété 'Mot de passe' dans le modèle de vue. PasswordBox doit être vide chaque fois que la fenêtre de connexion est appelée pendant que l'application est en cours d'exécution.(Par exemple, après la fermeture de la session en cours, l'utilisateur ne doit voir que Shell et fenêtre de connexion vides au-dessus du shell.) Mon problème est que le PasswordBox mentionné ci-dessus ne s'affiche que la première fois après le chargement de l'application. Si le PaswordBox est affiché en deuxième ou troisième fois par e.t.c, il n'est pas vide. S'il vous plaît voir l'image ci-dessous:Comment effacer WPF PasswordBox lié à ViewModel via Behavior?

enter image description here

Comme vous pouvez le voir mot de passe est vide, mais il doit être vide dans ce cas. Voici l'extrait de XAML de la fenêtre de connexion balisage où le PaswordBox est:

. . . . . . . . . . . . . . 
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
. . . . . . . . . . . . . . 
<PasswordBox Grid.Row="1" Grid.Column="1" Height="30" Margin="0 10 5 0" AutomationProperties.AutomationId="UserPasswordBox"> 
     <i:Interaction.Behaviors> 
      <behavior:PasswordBoxBindingBehavior Password="{Binding Password}"/> 
     </i:Interaction.Behaviors> 
</PasswordBox> 
. . . . . . . . . . . . . . . . 

Ci-dessous est la classe du comportement qui est également impliqué dans XAML que vous pouvez se dessus:

public class PasswordBoxBindingBehavior : Behavior<PasswordBox> 
{ 
    protected override void OnAttached() 
    { 
     AssociatedObject.PasswordChanged += OnPasswordBoxValueChanged; 
    } 

    public SecureString Password 
    { 
     get { return (SecureString)GetValue(PasswordProperty); } 
     set { SetValue(PasswordProperty, value); } 
    } 

    public static readonly DependencyProperty PasswordProperty = 
     DependencyProperty.Register("Password", typeof(SecureString), typeof(PasswordBoxBindingBehavior), new PropertyMetadata(null)); 

    private void OnPasswordBoxValueChanged(object sender, RoutedEventArgs e) 
    { 
     var binding = BindingOperations.GetBindingExpression(this, PasswordProperty); 
     if (binding != null) 
     { 
      PropertyInfo property = binding.DataItem.GetType().GetProperty(binding.ParentBinding.Path.Path); 
      if (property != null) 
       property.SetValue(binding.DataItem, AssociatedObject.SecurePassword, null); 
     } 
    } 
} 

Et ci-dessous est ' La propriété du mot de passe est dans le modèle de vue. Le PasswordBox est lié à cette propriété via PasswordBoxBindingBehavior:

public SecureString Password 
{ 
    get { return this._password; } 
    set { this.SetProperty(ref this._password, value); } 
} 

J'ai besoin que le PasswordBox soit vide chaque fois que la fenêtre se connecter est affiché pendant le fonctionnement de l'application. J'ai essayé d'effacer par programmation la propriété 'Mot de passe' dans le modèle de vue, mais cela n'aide pas. Comment puis-je le faire? S'il vous plaît aider.

Répondre

3

Vous pouvez brancher un PropertyChangedCallback pour la propriété de dépendance Password de votre comportement qui définit la propriété Password du PasswordBox à une chaîne vide lorsque la propriété source Password du modèle de vue est réglé sur null:

public class PasswordBoxBindingBehavior : Behavior<PasswordBox> 
{ 
    protected override void OnAttached() 
    { 
     AssociatedObject.PasswordChanged += OnPasswordBoxValueChanged; 
    } 

    public SecureString Password 
    { 
     get { return (SecureString)GetValue(PasswordProperty); } 
     set { SetValue(PasswordProperty, value); } 
    } 

    public static readonly DependencyProperty PasswordProperty = 
     DependencyProperty.Register("Password", typeof(SecureString), typeof(PasswordBoxBindingBehavior), new PropertyMetadata(OnSourcePropertyChanged)); 

    private static void OnSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if(e.NewValue == null) 
     { 
      PasswordBoxBindingBehavior behavior = d as PasswordBoxBindingBehavior; 
      behavior.AssociatedObject.PasswordChanged -= OnPasswordBoxValueChanged; 
      behavior.AssociatedObject.Password = string.Empty; 
      behavior.AssociatedObject.PasswordChanged += OnPasswordBoxValueChanged; 
     } 
    } 

    private static void OnPasswordBoxValueChanged(object sender, RoutedEventArgs e) 
    { 
     PasswordBox passwordBox = sender as PasswordBox; 
     var behavior = Interaction.GetBehaviors(passwordBox).OfType<PasswordBoxBindingBehavior>().FirstOrDefault(); 
     if(behavior != null) 
     { 
      var binding = BindingOperations.GetBindingExpression(behavior, PasswordProperty); 
      if (binding != null) 
      { 
       PropertyInfo property = binding.DataItem.GetType().GetProperty(binding.ParentBinding.Path.Path); 
       if (property != null) 
        property.SetValue(binding.DataItem, passwordBox.SecurePassword, null); 
      } 
     } 
    } 
} 

Ensuite, vous pouvez effacer le PasswordBox en définissant simplement la propriété source Password sur null dans votre modèle de vue.

+0

mm8, merci beaucoup pour votre aide. Maintenant, le mot de passe est effacé chaque fois que la fenêtre de connexion est affichée. – Prohor

+1

Donc, cela fonctionne comme prévu alors? S'il vous plaît n'oubliez pas d'accepter la réponse et votez-le: http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – mm8

+0

c'est très intelligent, me permet d'utiliser PasswordBox dans MVVM, merci pour l'idée et le code – ktingle