WPF 绑定密码

原文: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;
        }
    }
}



本文会经常更新,请阅读原文: https://blog.lindexi.com/post/WPF-%E7%BB%91%E5%AE%9A%E5%AF%86%E7%A0%81.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

如果你想持续阅读我的最新博客,请点击 RSS 订阅,推荐使用RSS Stalker订阅博客,或者前往 CSDN 关注我的主页

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

以下是广告时间

推荐关注 Edi.Wang 的公众号

原文地址:https://www.cnblogs.com/lonelyxmas/p/12082310.html

时间: 2024-10-10 06:44:05

WPF 绑定密码的相关文章

WPF绑定的ListBox获取ListBoxItem及GoToState应用

现公司项目中需要制作一个扇形菜单,菜单项是用ListBox重写Style实现的,其数据是绑定的.菜单的每一项都有Normal,MouseOver和Selected三种状态,这三种状态当然可以通过鼠标移动和点击控制,但现在要通过代码来改变控件外观实现三种状态切换,该如何处理呢?   1.WPF绑定的ListBox获取ListBoxItem WPF中如果ListBox的ItemSource为绑定的,则ListBox.Items为绑定的数据源,而非ListBoxItem.如果直接通过如下代码会发现无法

WPF绑定之索引器值变化通知

背景 在某些应用中,需要在界面上绑定到索引器,并在值发生变化时实时更新. 解决方案 只要将包含索引器的类实现INotifyPropertyChanged接口,并在索引值更改时引发PropertyChanged事件,并将属性名称设置为Item[]即可.示例代码如下: public class NotifyDictionary : INotifyPropertyChanged { private readonly Dictionary<string, string> _dictionary = n

WPF绑定

WPF绑定使用的源属性必须是依赖项属性,这是因为依赖项属性具有内置的更改通知支持,元素绑定表达式使用了Xaml扩展标记,WPF绑定一个控件是使用Binding.ElementName,绑定非控件对象时使用Source,RelativeSource,DataContext属性(WPF特有,而非XAML),只能绑定对象的共有字段.下边是部分Binding 属性名,完整列表参考 :http://msdn.microsoft.com/zh-cn/library/vstudio/ms750413.aspx

WPF快速入门系列(4)——深入解析WPF绑定

一.引言 WPF绑定使得原本需要多行代码实现的功能,现在只需要简单的XAML代码就可以完成之前多行后台代码实现的功能.WPF绑定可以理解为一种关系,该关系告诉WPF从一个源对象提取一些信息,并将这些信息来设置目标对象的属性.目标属性总是依赖属性.然而,源对象可以是任何内容,可以是一个WPF元素.或ADO.NET数据对象或自定义的数据对象等.下面详细介绍了WPF绑定中的相关知识点. 二.绑定元素对象 2.1 如何实现绑定元素对象 这里首先介绍绑定最简单的情况——绑定元素对象,即数据源是一个WPF元

[WPF]绑定到界面的数组不支持调度线程以外对其更改的办法

[原]WPF编程经常遇到一个问题: 某个数组己绑定到主界面某控件中,然后在后台程序中需要对数组增(减)数据,然后程序就会报错, 程序提示:该类型的CollectionView 不支持从调度程序线程以外的线程对其SourceCollection进行的更改. 如下图所示: 既然不能这样操作,就得想一个办法来解决,现在先把把出现错误的程序全部列出来,然后再来根据解决办法进行修改, 本测试程序先建一个学生类: using System; using System.Collections.Generic;

[WPF]实现密码框的密码绑定

正如绑定TextBox控件的Text属性一样, 我们希望能够将PasswordBox空间的Password属性进行绑定, 比如在MVVM模式中,这似乎是必须的, 但可惜的是, Password属性是不支持绑定的(不是依赖属性, 也没有实现INotifyPropertyChanged). 这可能是出于安全性的考虑. 但在我们的系统为了实现View层密码框中的密码与后台其它层之间的密码属性之间的绑定, 可以采取如下思路: 将密码框的密码和某一个缓冲区进行同步, 缓冲区在和后台进行绑定. 其中密码框与

WPF绑定BitMapImage

先说下图片文件存在服务器.wpf常用绑定图片地址没办法用.忽然想到,convert能否转字节数据?实验了下可以. 图片绑定字节数组. convert代码 public class PictureConvert : IValueConverter { /// <summary> /// 转换图片 /// </summary> /// <param name="value"></param> /// <param name="

WPF绑定Radiobutton到enum

WPF中经常会需要用到多个Radiobutton选择项,并且需要将选中的选项映射到某个枚举值enum中. 这种情形的解决办法如下: 1) 需要创建一个UserControl,举个例子代码如下: <UserControl x:Class="ShangfeiXApp.XModeUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="ht

WPF绑定到集合

什么是集合视图? 集合视图是位于绑定源集合顶部的一层,您可以通过它使用排序.筛选和分组查询来导航和显示源集合,而无需更改基础源集合本身.集合视图还维护着一个指向集合中的当前项的指针.如果源集合实现了 INotifyCollectionChanged 接口,则CollectionChanged 事件引发的更改将传播到视图. 如果将控件直接绑定到集合,则 WPF 会绑定到其默认视图.此默认视图由直接到同一集合的所有绑定共享,因此一个绑定控件或代码对默认视图所做的更改(如排序或对当前项指针的更改)会反