1. 程式人生 > >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。

還有一個簡單方法

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;
        }
    }
}

相關推薦

WPF 密碼

我們發現我們無法繫結密碼框的密碼,PasswordBox 的 Password 不能繫結。 我們想做 MVVM ,我們需要繫結密碼,不能使用前臺 xaml.cs 監聽 密碼改變得到密碼的值,傳到 ViewModel 。 本文提供一個簡單方法來繫結 WPF 的

WPF--自定義資料型別

WPF作為資料繫結的目標: 使用DataContext屬性,表示當前控制元件中的每個元素都繫結此資料: 資料型別定義: public class FamilyData { private string m_familyName; private string m_widt

WPF兩個ComboBox互相響應對方的選擇不成功請求幫助

windows2008無法執行.netremoting服務程式在XP,win2003下一切正常如何為ListView的每一ListViewItem新增MouseMove事件windows2008無法執行.netremoting服務程式在XP,win2003下一切正常如何為Li

wpf全域性靜態變數(mvvm)

原文 wpf繫結全域性靜態變數(mvvm) 在實際的開發中,有一些集合或者屬性可能是全域性的,比如當你做一個oa的時候,可能需要展示所有的人員,這時這個所有的人員列表顯然可以作為全域性引數,比如這裡有一個全域性的靜態屬性UserList。而你在使用mvvm做wpf開發的時候,一般每個view都已經

LibVLC.NET 與WPF播放器

先決條件LibVLC.NET提供.NET繫結到VLC媒體播放器的LibVLC核心庫(libVLC)。由於使用了一些更新的LibVLC功能,LibVLC.NET需要VLC版本1.2,可以在這裡下載。如果您已將VLC媒體播放器(1.2)安裝在其預設位置(例如C:\ Program

WPF之索引器值變化通知

原文: WPF繫結之索引器值變化通知 背景 在某些應用中,需要在介面上繫結到索引器,並在值發生變化時實時更新。 解決方案 只要將包含索引器的類實現INotifyPropertyChanged介面,並在索引值更改時引發PropertyChanged事件,並將屬性名稱設定為Item[]即可。示例程式碼如下

WPF模式

<Window x:Class="WPF_Started.Controls.DataBinding.BindingMode"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x

WPF不到父控制元件屬性

原因: 如果A控制元件並不是屬於visual tree的部分,那麼他不能連線到他父控制元件的datacontext,也就不能繫結到父控制元件的屬性 解決方案: 使用一個Freezable做代理 public class BindingProx

WPF概念基礎(四大組成,方向,觸發)

    本文為原創文章,可以轉載但不得商用,轉載必須註明來源。    今天講述的是一個關於WPF繫結的小例子,學習好WPF繫結,幾乎可以達到邏輯和介面完全隔離的神奇效果。    關於邏輯和介面是否可以完全可以隔離,我想告訴大家的是,如果學好了繫結機制和內部執行原理,是可以達到

wpf 表示式和手動更新源

<Window x:Class="BindingExpressionExam.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmln

菜鳥做wpfxml使遇到很多問題,跪求解

跪求各位高手,菜鳥在做wpf繫結xml操作,遇到以下難題,求各位高手:wpf 繫結 xml 為資料來源的圖片繫結(及佈局)方法,單擊按鈕改變屬性:如下圖單擊Button,改變ID、Name、Age、Sex中的任何一個或幾個屬性值,急求,謝謝

WPF -- 顯示多個屬性

參考: 方法1: DataTemplate 包含一個 StackPanel; StackPanel 包含多個 TextBlock; 一個屬性繫結到一個 TextBlock。 (我比較喜歡的) XAML程式碼 <ItemsControl ItemsSource="{Binding Path=.}"&

WPF入門

一 概述 文章一開始,將給出一個使用WPF繫結的小例項。並以此為起點,逐步展開對WPF繫結知識的探討。 二 例項演示 1新建WPF應用程式WpfBindingExp,下面是程式主畫面的程式碼。 <pre name="code" class="html">&l

WPF資料來源之RelativeSource

一.FindAncestor 有時候我們不確定作為資料來源的物件叫什麼名字,但知道作為繫結源與UI佈局有相對的關係,如下是一段XAML程式碼,說明多層佈局控制元件中放置一個文字控制元件,來顯示父級控制元件的名稱。 1、XAML Html程式碼:  <Grid x:Name="g1" Background

WPF 中Converter的應用

在WPF 經常用到繫結,如果繫結的源資料和目標屬性是同類型的則不需要轉換。比如 <TextBox x:Name="txt1" Background="Blue" Text="測試"/> <TextBox Ba

WPF失效問題(規避解決)

使用WPF繫結後臺資料,在多次切換資料後繫結失效 將一個後臺資料繫結到多個RadioButton的IsChecked上,通過自定義轉換將整型資料轉換成bool型資料。點選介面上的新增按鈕,在button事件中,將繫結的物件資料加1,然後再前臺顯示,在多次後,前

WPF(Binding)物件集合修改顯示屬性問題

問題描述:我打算選中列表中的欄位,用文字框的值替換選中的欄位。然而在使用Binging將存放自定義類(Student)的集合繫結到ListBox上,顯示的是這個類的“Name”屬性。在修改這個屬性後卻沒有看到列表中選中欄位的變化。ListBox取值繫結儲存Sutdent類的物

wpf 資料無法更新ui控制元件可能存在的問題

BindingMode的列舉值有: ① OneWay ② TwoWay ③ OneTime:根據源端屬性值設定目標屬性值,之後的改變會被忽略,除非呼叫BindingExpression.UpdateTarge方法 ④ OneWayToSource:與OneWay類似,

WPF到linq表示式

using ClassLibrary;using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Linq;using System.Text;

wpf MVVM passwordbox密碼問題簡單解決辦法

      網上關於這個方案的解決辦法都比較複雜,所以才來寫這篇部落格提供一種簡單方法。   本來沒有在意這個問題,直到突然有一個發現passwordbox為了安全性把password屬性做成了非依賴屬性,不能進行繫結也不能進行屬性值變化監聽,網上搜了一些資料發現解決辦法都比