zoukankan      html  css  js  c++  java
  • [WPF]实现密码框的密码绑定

        正如绑定TextBox控件的Text属性一样, 我们希望能够将PasswordBox空间的Password属性进行绑定, 比如在MVVM模式中,这似乎是必须的, 但可惜的是, Password属性是不支持绑定的(不是依赖属性, 也没有实现INotifyPropertyChanged). 
    这可能是出于安全性的考虑. 但在我们的系统为了实现View层密码框中的密码与后台其它层之间的密码属性之间的绑定, 可以采取如下思路: 将密码框的密码和某一个缓冲区进行同步, 缓冲区在和后台进行绑定. 其中密码框与缓冲区之间的同步可采用事件进行通知, 并将缓冲区打造成依赖属性, 然后缓冲区就支持绑定了, 并给后台提供正确的密码.
    缓冲区可以是哈希表或其他字典结构, 以便将密码框和缓冲区中的密码一 一对应起来, 也可以使AttachProperty(附加属性), 其实附加属性的机制也就是对缓存了的一个大字典进行操作

    复制代码
        public static class PasswordBoxBindingHelper
        {
            public static bool GetIsPasswordBindingEnabled(DependencyObject obj)
            {
                return (bool)obj.GetValue(IsPasswordBindingEnabledProperty);
            }

            public static void SetIsPasswordBindingEnabled(DependencyObject obj, bool value)
            {
                obj.SetValue(IsPasswordBindingEnabledProperty, value);
            }

            public static readonly DependencyProperty IsPasswordBindingEnabledProperty =
                DependencyProperty.RegisterAttached("IsPasswordBindingEnabled", typeof(bool), 
                typeof(PasswordBoxBindingHelper), 
                new UIPropertyMetadata(false, OnIsPasswordBindingEnabledChanged));

            private static void OnIsPasswordBindingEnabledChanged(DependencyObject obj, 
                                                                  DependencyPropertyChangedEventArgs e)
            {
                var passwordBox = obj as PasswordBox;

                if(passwordBox != null)
                {
                    passwordBox.PasswordChanged -= PasswordBoxPasswordChanged;

                    if ((bool)e.NewValue)
                    {
                        passwordBox.PasswordChanged += PasswordBoxPasswordChanged;
                    }
                   
                }
            }

            //when the passwordBox's password changed, update the buffer
            static void PasswordBoxPasswordChanged(object sender, RoutedEventArgs e)
            {
                var passwordBox = (PasswordBox) sender;

                if (!String.Equals(GetBindedPassword(passwordBox),passwordBox.Password))
                {
                    SetBindedPassword(passwordBox, passwordBox.Password);
                }
            }


            public static string GetBindedPassword(DependencyObject obj)
            {
                return (string)obj.GetValue(BindedPasswordProperty);
            }


            public static void SetBindedPassword(DependencyObject obj, string value)
            {
                obj.SetValue(BindedPasswordProperty, value);
            }

            public static readonly DependencyProperty BindedPasswordProperty =
                DependencyProperty.RegisterAttached("BindedPassword", typeof(string), 
                typeof(PasswordBoxBindingHelper), 
                new UIPropertyMetadata(string.Empty, OnBindedPasswordChanged));

            //when the buffer changed, upate the passwordBox's password
            private static void OnBindedPasswordChanged(DependencyObject obj, 
                                                        DependencyPropertyChangedEventArgs e)
            {
                var passwordBox = obj as PasswordBox;
                if (passwordBox != null)
                {

                    passwordBox.Password = e.NewValue == null ? string.Empty : e.NewValue.ToString();
                }
            }       

        }
     
     
    在View层, 如下使用便可以了:
     
     
     
     
    另外, 在更改了密码框的密码后, 需要手动更新密码框插入符(CaretIndex)的位置, 可惜的是, 密码框并没有给我们提供这样的属性或方法(TextBox有, PasswordBox没有), 可以采用下面的方法来设置:
     
    private static void SetPasswordBoxSelection(PasswordBox passwordBox, int start, int length)
            {
                var select = passwordBox.GetType().GetMethod("Select", 
                                BindingFlags.Instance | BindingFlags.NonPublic);

                select.Invoke(passwordBox, new object[] { start, length });
            }
     
     
    在view中添加:
     
    <PasswordBox x:Name="pbPassword"  Grid.Row="1" Grid.Column="2" MaxWidth="300" Width="300" HorizontalAlignment="Center" VerticalAlignment="Center"
                  local:PasswordBoxBindingHelper.IsPasswordBindingEnabled="True"
                  local:PasswordBoxBindingHelper.BindedPassword= "{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                  PasswordChanged="pbPassword_PasswordChanged"
                 />
     
    然后在view的cs(后台代码中)添加:
     
     
    private void pbPassword_PasswordChanged(object sender, RoutedEventArgs e)
    {
        PasswordBox passwordtext = (PasswordBox)sender;
        SetPasswordBoxSelection(passwordtext, passwordtext.Password.Length + 1, passwordtext.Password.Length + 1);
    }
     
    private static void SetPasswordBoxSelection(PasswordBox passwordBox, int start, int length)
    {
        var select = passwordBox.GetType().GetMethod("Select",
                        BindingFlags.Instance | BindingFlags.NonPublic);
     
        select.Invoke(passwordBox, new object[] { start, length });
    }
  • 相关阅读:
    第18章 检测点模型
    第17章 发现过拟合和欠拟合
    第16章 学习速率调度器
    第15章 MiniVGGNet:更深的CNNs
    第14章 LeNet:识别手写数字
    第13章保存和加载你的模型
    第12章 训练你的第一个CNN
    Vue.js
    python3第一天
    R+JAVA 中文乱码问题
  • 原文地址:https://www.cnblogs.com/changbaishan/p/4239177.html
Copyright © 2011-2022 走看看