我们发现我们无法绑定密码框的密码,PasswordBox 的 Password 不能绑定。 我们想做 MVVM ,我们需要绑定密码,不能使用前台 xaml.cs 监听 密码改变得到密码的值,传到 ViewModel 。 本文提供一个简单方法来绑定 WPF 的 PasswordBox 的 Password 。这种方法不仅在 WPF 可以使用,在 UWP 也可以使用。关于 UWP 绑定密码,可以在我博客 win10 uwp 绑定密码 查看。
我在网上找的很多大神给出的可以解决绑定密码的方法,下面是我找的一个简单方法。
首先需要新建一个类 PasswordHelper ,他是一个静态类,当然不是静态也没关系,但是一般写静态的可以让我们少犯错,因为我们所有属性等都是需要静态的。
    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;            if (passwordBox != null)            {                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;            if (passwordBox != null)            {                SetIsUpdating(passwordBox, true);                SetPassword(passwordBox, passwordBox.Password);                SetIsUpdating(passwordBox, false);            }        }    }写完我们就可以使用他,使用很简单,在我们需要密码框的页面的xaml 上写两行新的代码就好。
<PasswordBox local:PasswordHelper.Attach="True"                             local:PasswordHelper.Password="{Binding Password, Mode=TwoWay}"                             Width="180" Style="{DynamicResource PasswordBoxStyle}"/>其中,Password 是 ViewModel 的PassWord,很简单我们把PasswordBox 绑定到ViewModel。
PASSWORDPROPERTY是附加属性,REGISTERATTACHED 就是注册附加。
我们附加属性是回调,当属性变化使用函数。
我们需要设置Attach,设置时调用static void Attach(DependencyObject sender,           DependencyPropertyChangedEventArgs e)
在 Attach 触发,首先要判断设置的 sender 是不是 Password
            PasswordBox passwordBox = sender as PasswordBox;
            if (passwordBox == null)            {                return;            }判断改变的值,Old是true还是false,如果是true,那么之前用了事件,我们要把事件
passwordBox.PasswordChanged -= PasswordChanged;如果之前是false,那么没绑定,我们不能删除。
判断要改变的,如果是true,我们就
passwordBox.PasswordChanged += PasswordChanged;如果不是,我们就不使用。
我们使用了是否存在密码修改就使用PasswordChanged函数。也就是设置了刚才的就可在密码变化使用PasswordChanged。
我们在PasswordChanged判断输入是不是PasswordBox,把密码传进PasswordProperty。
参见:http://www.wpftutorial.net/PasswordBox.html
还有一个简单方法
using System.Windows;using System.Windows.Controls;
namespace CustomControl{    public class BindablePasswordBox : Decorator    {        /// <summary>        /// The password dependency property.        /// </summary>        public static readonly DependencyProperty PasswordProperty;
        private bool isPreventCallback;        private RoutedEventHandler savedCallback;
        /// <summary>        /// Static constructor to initialize the dependency properties.        /// </summary>        static BindablePasswordBox()        {            PasswordProperty = DependencyProperty.Register(                "Password",                typeof(string),                typeof(BindablePasswordBox),                new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnPasswordPropertyChanged))            );        }
        /// <summary>        /// Saves the password changed callback and sets the child element to the password box.        /// </summary>        public BindablePasswordBox()        {            savedCallback = HandlePasswordChanged;
            PasswordBox passwordBox = new PasswordBox();            passwordBox.PasswordChanged += savedCallback;            Child = passwordBox;        }
        /// <summary>        /// The password dependency property.        /// </summary>        public string Password        {            get { return GetValue(PasswordProperty) as string; }            set { SetValue(PasswordProperty, value); }        }
        /// <summary>        /// Handles changes to the password dependency property.        /// </summary>        /// <param name="d">the dependency object</param>        /// <param name="eventArgs">the event args</param>        private static void OnPasswordPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs eventArgs)        {            BindablePasswordBox bindablePasswordBox = (BindablePasswordBox) d;            PasswordBox passwordBox = (PasswordBox) bindablePasswordBox.Child;
            if (bindablePasswordBox.isPreventCallback)            {                return;            }
            passwordBox.PasswordChanged -= bindablePasswordBox.savedCallback;            passwordBox.Password = (eventArgs.NewValue != null) ? eventArgs.NewValue.ToString() : "";            passwordBox.PasswordChanged += bindablePasswordBox.savedCallback;        }
        /// <summary>        /// Handles the password changed event.        /// </summary>        /// <param name="sender">the sender</param>        /// <param name="eventArgs">the event args</param>        private void HandlePasswordChanged(object sender, RoutedEventArgs eventArgs)        {            PasswordBox passwordBox = (PasswordBox) sender;
            isPreventCallback = true;            Password = passwordBox.Password;            isPreventCallback = false;        }    }}
  原文链接: http://blog.lindexi.com/post/WPF-%E7%BB%91%E5%AE%9A%E5%AF%86%E7%A0%81
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。 欢迎转载、使用、重新发布,但务必保留文章署名 林德熙 (包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我 联系。