[WPF]實現密碼框的密碼綁定

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章