...
authorStricted <info@stricted.de>
Tue, 12 Jan 2016 17:39:01 +0000 (18:39 +0100)
committerStricted <info@stricted.de>
Tue, 12 Jan 2016 17:39:01 +0000 (18:39 +0100)
SpeedportHybridControl.Implementations/PasswordHelper.cs
SpeedportHybridControl/page/LoginPage.xaml

index 316a8152cfbbe8234afcf62d53980e2eb275392b..775e9ff05d06d02cf0c6d49b055763c70ed96722 100644 (file)
@@ -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);
                }
        }
 }
index b3e1f597283cc97bb5b3956e3aa1365e515b263e..e6c9d7c3918f597d0cbe93416ab0882bebb164ff 100644 (file)
@@ -15,7 +15,7 @@
             <TextBox Text="{Binding Path=ip, Mode=TwoWay}" HorizontalAlignment="Left" Height="23" Margin="115,14,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
 
             <TextBlock Text="Passwort:" HorizontalAlignment="Left" Margin="55,49,0,0" VerticalAlignment="Top" />
-            <PasswordBox Implementations:PasswordHelper.Password="{Binding Path=password, Mode=TwoWay, NotifyOnSourceUpdated=True}"  Visibility="{Binding Path=PasswordBoxVisibility}" x:Name="passwordBox" HorizontalAlignment="Left" Height="23" Margin="115,42,0,0" VerticalAlignment="Top" Width="120" ForceCursor="True" />
+            <PasswordBox Implementations:PasswordHelper.BindPassword="true" Implementations:PasswordHelper.BoundPassword="{Binding Path=password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  Visibility="{Binding Path=PasswordBoxVisibility}" x:Name="passwordBox" HorizontalAlignment="Left" Height="23" Margin="115,42,0,0" VerticalAlignment="Top" Width="120" ForceCursor="True" />
             <TextBox Text="{Binding Path=password, Mode=TwoWay}" HorizontalAlignment="Left" Height="23" Margin="115,42,0,0" VerticalAlignment="Top" Width="120" Visibility="{Binding Path=PasswordTextBoxVisibility}"/>
             <CheckBox Command="{Binding Path=ShowPasswordCommand}" IsChecked="{Binding Path=ShowPassword, Mode=TwoWay}" Content="Passwort anzeigen" Margin="240,50,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />
             <CheckBox Command="{Binding Path=SavePasswordCommand}" IsChecked="{Binding Path=SavePassword, Mode=TwoWay}" Content="Passwort speichern" Margin="240,65,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" />