【问题标题】:How to clear WPF PasswordBox bound to ViewModel via Behavior?如何通过行为清除绑定到 ViewModel 的 WPF PasswordBox?
【发布时间】:2017-02-18 12:51:25
【问题描述】:

我编写 WPF MVVM Prism 6.2 应用程序。在登录窗口(即 PrismUserControl)的视图中,我有一个 PaswordBox 绑定(通过行为)到视图模型中的“密码”属性。 每次在应用程序运行时调用登录窗口时,PasswordBox 必须为空。 (例如,在用户关闭当前会话后,他或她必须只看到空的 Shell 和 Shell 上方的登录窗口.) 我的问题是上述密码框仅在应用程序加载后第一次显示为空。如果密码框在第二次或第三次等中显示,则它不为空。请看下图:

如您所见,密码不为空,但在这种情况下必须为空。下面是来自登录窗口标记的 XAML sn-p,其中 PaswordBox 是:

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

下面是 XAML 中也涉及的行为类别,如您在上面看到的:

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

下面是视图模型中的“密码”属性。 PasswordBox 通过 PasswordBoxBindingBehavior 绑定到该属性:

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

在应用程序工作期间,每次显示登录窗口时,我都需要 PasswordBox 为空。我试图以编程方式清除视图模型中的“密码”属性,但没有帮助。我该怎么做?请帮忙。

【问题讨论】:

    标签: c# wpf mvvm behavior


    【解决方案1】:

    您可以为您的行为的Password 依赖属性连接一个PropertyChangedCallback,当视图模型的Password 源属性设置时,将PasswordBoxPassword 属性设置为空字符串给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);
                }
            }
        }
    }
    

    然后,您只需在视图模型中将 Password 源属性设置为 null 即可清除 PasswordBox

    【讨论】:

    • mm8,非常感谢您的帮助。现在每次显示登录窗口时密码都会被清除。
    • 那么它可以按预期工作吗?请记住接受答案并投票:meta.stackexchange.com/questions/5234/…
    • 这很聪明,让我可以在 MVVM 中使用 PasswordBox,谢谢你的想法和代码
    • 你好。这是一个很好的答案,但它不适用于编写如下的绑定:Password="{Binding Path=(local:MyViewModel.Password)}。在这种情况下,“binding.ParentBinding.Path.Path”值为“(0) ” 所以该属性为空。但 Kevin Kalitowski 的答案适用于框架 4.5 及更高版本:stackoverflow.com/a/9603656/4049478。它取代了“binding.ParentBinding。 ...”与“binding.ResolvedSourcePropertyName”。
    【解决方案2】:

    一种更简单的方法。每次屏幕(PasswordBox 元素所在的 Grid)关闭时,这都会清除 passwordBox 文本框。

    <Grid  Grid.LostFocus="event_method" ...
    
    <PasswordBox x:Name="passwordBox" ...
    

    在后面的代码中:

    public event_method()
    {
        passwordBox.Clear();
    }
    

    【讨论】:

      猜你喜欢
      • 2017-10-18
      • 2017-12-28
      • 2015-09-10
      • 2011-02-01
      • 2010-12-05
      • 1970-01-01
      • 1970-01-01
      • 2015-11-24
      • 2011-02-08
      相关资源
      最近更新 更多