zoukankan      html  css  js  c++  java
  • WPF 绑定密码

    我们发现我们无法绑定密码框的密码,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://lindexi.oschina.io/lindexi/post/WPF-%E7%BB%91%E5%AE%9A%E5%AF%86%E7%A0%81/

    知识共享许可协议
    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

  • 相关阅读:
    spring boot 若依系统整合Ueditor,部署时候上传图片错误解决
    JVM学习笔记之栈区
    据说这个是可以撸到2089年的idea2020.2
    小程序监听屏幕滑动事件
    小程序bindinput和bindblur赋值延迟问题解决
    小程序文件下载并保存文件名打开
    数据结构
    Spring JPA 自定义删改
    Spring JPA 查询创建
    Spring JPA 拓展
  • 原文地址:https://www.cnblogs.com/lindexi/p/7694408.html
Copyright © 2011-2022 走看看