[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层, 如下使用便可以了:

<PasswordBox  Helpers:PasswordBoxBindingHelper.IsPasswordBindingEnabled="True" 
                     Helpers:PasswordBoxBindingHelper.BindedPassword=
                     "{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

另外, 在更改了密码框的密码后, 需要手动更新密码框插入符(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 });

}

时间: 2024-11-06 12:47:43

[WPF]实现密码框的密码绑定的相关文章

[入门]打破***的原型,网页中的密码框的密码显示出来

刚才把家里的ADSL的密码给忘记了,好不开心,于是在路由器的配置网页上面找了找去,希望能够找到点蛛丝马迹. 找到PPPoE连接的密码框,可惜它是被***包裹的. 于是掏出开发者工具,找到对应的节点,把type="password"删除即可达到我们的效果. [入门]打破***的原型,网页中的密码框的密码显示出来

WPF 之 文本框及密码框添加水印效果

1.文本框添加水印效果 文本框水印相对简单,不需要重写模板,仅仅需要一个 VisualBrush 和触发器验证一下Text是否为空即可. <TextBox Name="txtSerachDataName" Width="120" Height="23" Grid.Column="3" Grid.Row="1"> <TextBox.Resources> <VisualBrush

密码框密码不能绑定问题解决方案

想要扩展该控件时发现PasswordBox是一个密封类,是不可继承的. 故通过附加属性来实现该功能. 声明了两个附加属性 IsPasswordBindingEnabled:用来指示密码是否可用来绑定,当值发生改变时订阅或者取消订阅当Password改变时同步用于绑定的密码附加属性 BindedPassword:用于绑定的密码,与密码同步,当值发生改变是时与Password同步 /// <summary> /// 扩展密码框密码可用于绑定的帮助类 /// </summary> pub

WPF自定义控件之水印文本(密码)框

首先来讲讲创建这个控件的初衷,一个让我很郁闷的问题. 公司的客户端项目采用WPF+MVVM技术实现,在近期地推客户端的过程中遇到了一个很奇葩的问题:在登录界面点击密码框就会直接闪退,没有任何提示 密码框是WPF原生的PasswordBox,这似乎没有什么不对.出现这个情况的一般是在xp系统(ghost的雨林木风版本或番茄花园),某些xp系统又不会出现. 出现这个问题的原因是因为客户的系统缺少PasswordBox使用的某种默认的字体,网上有人说是times new roman,又或者其它某种字体

WPF文本框密码框添加水印效果

WPF文本框密码框添加水印效果 来源: 阅读:559 时间:2014-12-31 分享: 0 按照惯例,先看下效果 文本框水印 文本框水印相对简单,不需要重写模板,仅仅需要一个VisualBrush   和触发器验证一下Text是否为空即可. 上代码: <TextBox Name="txtSerachDataName" Width="120" Height="23" Grid.Column="3" Grid.Row=&q

iOS密码框的实现方式

说一下密码加密的实现方式 效果图: 实现方式: 主要说一下密码框的实现,这个密码框中间的四个数字其实是4个 UITextField ,然后通过键盘删除键 和TextFiled 的协议shouldChangeCharactersInRange.来判断输入的位置,代码如下: 直接上代码: // //  IDSGameRoomSecretView.h // //  Created by levi.duan on 2017/7/18. //  Copyright ? 2017年 Near. All ri

实现密码框默认文字效果实例代码

实现密码框默认文字效果实例代码:大家都知道很多文本框在默认情况下都有默认的提示文本,例如"请输入姓名"之类的语言,当点击文本框的时候,会清除提示语,比较人性化.但是在密码框中实现此效果可能就有点麻烦了,因为密码框不是以明文显示的,下面就介绍一下代码实例解决此问题.代码如下: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="

Android 判断EditView是否为密码框

最近在做项目的时候需自动判断,一个登陆页面中EditView是否为密码框,我们可以使用inPutType属性来判断,我们可以利用getInputType()来判断,getInputType == 129时EditView就是一个密码框.

iOS密码框实现(二)取消确定按钮

由于将确定按钮去掉了,所以需要重新修改下代码,当输入第四个数字时,自动进入房间. iOS 密码框效果图: 实现方式: 首先声明一个block初始化方法,因为这只是个框框,并不需要处理网络请求等等,需要提供一个block给调用方,调用方利用block 去拿到密码,利用密码做一些开房间等操作. 利用计时器通过0.2秒来看清输入第四位密码,用户输入4位密码后自动进入下一步操作. 1.头文件需要定义: @classIDSGameRoomSecretView; typedefvoid(^selfhandl