From 1fa45847c67b401682e2d634822c33d5b2dde227 Mon Sep 17 00:00:00 2001 From: Stricted Date: Tue, 12 Jan 2016 18:39:01 +0100 Subject: [PATCH] ... --- .../PasswordHelper.cs | 115 ++++++++++++------ SpeedportHybridControl/page/LoginPage.xaml | 2 +- 2 files changed, 77 insertions(+), 40 deletions(-) diff --git a/SpeedportHybridControl.Implementations/PasswordHelper.cs b/SpeedportHybridControl.Implementations/PasswordHelper.cs index 316a815..775e9ff 100644 --- a/SpeedportHybridControl.Implementations/PasswordHelper.cs +++ b/SpeedportHybridControl.Implementations/PasswordHelper.cs @@ -5,55 +5,92 @@ using System.Windows.Data; namespace SpeedportHybridControl.Implementations { - // see http://antonymale.co.uk/2015/08/binding-to-a-passwordbox-password-in-wpf + // http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html public static class PasswordHelper { - private static readonly DependencyProperty PasswordInitializedProperty = - DependencyProperty.RegisterAttached("PasswordInitialized", typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false)); - - private static readonly DependencyProperty SettingPasswordProperty = - DependencyProperty.RegisterAttached("SettingPassword", typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false)); - - public static string GetPassword (DependencyObject obj) { - return (string)obj.GetValue(PasswordProperty); - } - public static void SetPassword (DependencyObject obj, string value) { - obj.SetValue(PasswordProperty, value); - } - // We play a trick here. If we set the initial value to something, it'll be set to something else when the binding kicks in, - // and HandleBoundPasswordChanged will be called, which allows us to set up our event subscription. - // If the binding sets us to a value which we already are, then this doesn't happen. Therefore start with a value that's - // definitely unique. - public static readonly DependencyProperty PasswordProperty = - DependencyProperty.RegisterAttached("Password", typeof(string), typeof(PasswordHelper), - new FrameworkPropertyMetadata(Guid.NewGuid().ToString(), HandleBoundPasswordChanged) { - BindsTwoWayByDefault = true, - DefaultUpdateSourceTrigger = UpdateSourceTrigger.LostFocus // Match the default on Binding - }); - - private static void HandleBoundPasswordChanged (DependencyObject dp, DependencyPropertyChangedEventArgs e) { - var passwordBox = dp as PasswordBox; - if (passwordBox == null) + public static readonly DependencyProperty BoundPassword = + DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordHelper), new PropertyMetadata(string.Empty, OnBoundPasswordChanged)); + + public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached( + "BindPassword", typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false, OnBindPasswordChanged)); + + private static readonly DependencyProperty UpdatingPassword = + DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false)); + + private static void OnBoundPasswordChanged (DependencyObject d, DependencyPropertyChangedEventArgs e) { + PasswordBox box = d as PasswordBox; + + // only handle this event when the property is attached to a PasswordBox + // and when the BindPassword attached property has been set to true + if (d == null || !GetBindPassword(d)) { return; + } + + // avoid recursive updating by ignoring the box's changed event + box.PasswordChanged -= HandlePasswordChanged; - // If we're being called because we set the value of the property we're bound to (from inside - // HandlePasswordChanged, then do nothing - we already have the latest value). - if ((bool)passwordBox.GetValue(SettingPasswordProperty)) + string newPassword = (string)e.NewValue; + + if (!GetUpdatingPassword(box)) { + box.Password = newPassword; + } + + box.PasswordChanged += HandlePasswordChanged; + } + + private static void OnBindPasswordChanged (DependencyObject dp, DependencyPropertyChangedEventArgs e) { + // when the BindPassword attached property is set on a PasswordBox, + // start listening to its PasswordChanged event + + PasswordBox box = dp as PasswordBox; + + if (box == null) { return; + } + + bool wasBound = (bool)(e.OldValue); + bool needToBind = (bool)(e.NewValue); - // If this is the initial set (see the comment on PasswordProperty), set ourselves up - if (!(bool)passwordBox.GetValue(PasswordInitializedProperty)) { - passwordBox.SetValue(PasswordInitializedProperty, true); - passwordBox.PasswordChanged += HandlePasswordChanged; + if (wasBound) { + box.PasswordChanged -= HandlePasswordChanged; } - passwordBox.Password = e.NewValue as string; + if (needToBind) { + box.PasswordChanged += HandlePasswordChanged; + } } private static void HandlePasswordChanged (object sender, RoutedEventArgs e) { - var passwordBox = (PasswordBox)sender; - passwordBox.SetValue(SettingPasswordProperty, true); - SetPassword(passwordBox, passwordBox.Password); - passwordBox.SetValue(SettingPasswordProperty, false); + PasswordBox box = sender as PasswordBox; + + // set a flag to indicate that we're updating the password + SetUpdatingPassword(box, true); + // push the new password into the BoundPassword property + SetBoundPassword(box, box.Password); + SetUpdatingPassword(box, false); + } + + public static void SetBindPassword (DependencyObject dp, bool value) { + dp.SetValue(BindPassword, value); + } + + public static bool GetBindPassword (DependencyObject dp) { + return (bool)dp.GetValue(BindPassword); + } + + public static string GetBoundPassword (DependencyObject dp) { + return (string)dp.GetValue(BoundPassword); + } + + public static void SetBoundPassword (DependencyObject dp, string value) { + dp.SetValue(BoundPassword, value); + } + + private static bool GetUpdatingPassword (DependencyObject dp) { + return (bool)dp.GetValue(UpdatingPassword); + } + + private static void SetUpdatingPassword (DependencyObject dp, bool value) { + dp.SetValue(UpdatingPassword, value); } } } diff --git a/SpeedportHybridControl/page/LoginPage.xaml b/SpeedportHybridControl/page/LoginPage.xaml index b3e1f59..e6c9d7c 100644 --- a/SpeedportHybridControl/page/LoginPage.xaml +++ b/SpeedportHybridControl/page/LoginPage.xaml @@ -15,7 +15,7 @@ - + -- 2.20.1