|
| 1 | +// Copyright (c) 2021, Phoenix Contact GmbH & Co. KG |
| 2 | +// Licensed under the Apache License, Version 2.0 |
| 3 | + |
| 4 | +using System.Windows; |
| 5 | +using System.Windows.Controls; |
| 6 | + |
| 7 | +namespace Moryx.WpfToolkit |
| 8 | +{ |
| 9 | + /// <summary> |
| 10 | + /// Helper class for the password box to bind the password |
| 11 | + /// </summary> |
| 12 | + public static class PasswordBoxHelper |
| 13 | + { |
| 14 | + /// <summary> |
| 15 | + /// Attached property for the bound password |
| 16 | + /// </summary> |
| 17 | + public static readonly DependencyProperty BoundPassword = |
| 18 | + DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxHelper), new PropertyMetadata(string.Empty, OnBoundPasswordChanged)); |
| 19 | + |
| 20 | + /// <summary> |
| 21 | + /// Attached property for the bind password |
| 22 | + /// </summary> |
| 23 | + public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached( |
| 24 | + "BindPassword", typeof(bool), typeof(PasswordBoxHelper), new PropertyMetadata(false, OnBindPasswordChanged)); |
| 25 | + |
| 26 | + private static readonly DependencyProperty UpdatingPassword = |
| 27 | + DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxHelper), new PropertyMetadata(false)); |
| 28 | + |
| 29 | + /// <summary> |
| 30 | + /// Gets the <see cref="BindPassword"/> value |
| 31 | + /// </summary> |
| 32 | + public static bool GetBindPassword(DependencyObject dp) => |
| 33 | + (bool)dp.GetValue(BindPassword); |
| 34 | + |
| 35 | + /// <summary> |
| 36 | + /// Sets the <see cref="BindPassword"/> value |
| 37 | + /// </summary> |
| 38 | + public static void SetBindPassword(DependencyObject dp, bool value) => |
| 39 | + dp.SetValue(BindPassword, value); |
| 40 | + |
| 41 | + /// <summary> |
| 42 | + /// Gets the <see cref="BoundPassword"/> value |
| 43 | + /// </summary> |
| 44 | + public static string GetBoundPassword(DependencyObject dp) => |
| 45 | + (string)dp.GetValue(BoundPassword); |
| 46 | + |
| 47 | + /// <summary> |
| 48 | + /// Sets the <see cref="BoundPassword"/> value |
| 49 | + /// </summary> |
| 50 | + public static void SetBoundPassword(DependencyObject dp, string value) => |
| 51 | + dp.SetValue(BoundPassword, value); |
| 52 | + |
| 53 | + private static bool GetUpdatingPassword(DependencyObject dp) => |
| 54 | + (bool)dp.GetValue(UpdatingPassword); |
| 55 | + |
| 56 | + private static void SetUpdatingPassword(DependencyObject dp, bool value) => |
| 57 | + dp.SetValue(UpdatingPassword, value); |
| 58 | + |
| 59 | + private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
| 60 | + { |
| 61 | + var box = d as PasswordBox; |
| 62 | + |
| 63 | + // only handle this event when the property is attached to a PasswordBox |
| 64 | + // and when the BindPassword attached property has been set to true |
| 65 | + if (d == null || !GetBindPassword(d)) |
| 66 | + return; |
| 67 | + |
| 68 | + // avoid recursive updating by ignoring the box's changed event |
| 69 | + box.PasswordChanged -= HandlePasswordChanged; |
| 70 | + |
| 71 | + var newPassword = (string)e.NewValue; |
| 72 | + |
| 73 | + if (!GetUpdatingPassword(box)) |
| 74 | + box.Password = newPassword; |
| 75 | + |
| 76 | + box.PasswordChanged += HandlePasswordChanged; |
| 77 | + } |
| 78 | + |
| 79 | + private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e) |
| 80 | + { |
| 81 | + // When the BindPassword attached property is set on a PasswordBox, |
| 82 | + // start listening to its PasswordChanged event |
| 83 | + if (dp is not PasswordBox box) |
| 84 | + return; |
| 85 | + |
| 86 | + var wasBound = (bool)e.OldValue; |
| 87 | + var needToBind = (bool)e.NewValue; |
| 88 | + |
| 89 | + if (wasBound) |
| 90 | + box.PasswordChanged -= HandlePasswordChanged; |
| 91 | + |
| 92 | + if (needToBind) |
| 93 | + box.PasswordChanged += HandlePasswordChanged; |
| 94 | + } |
| 95 | + |
| 96 | + private static void HandlePasswordChanged(object sender, RoutedEventArgs e) |
| 97 | + { |
| 98 | + var box = sender as PasswordBox; |
| 99 | + |
| 100 | + // set a flag to indicate that we're updating the password |
| 101 | + SetUpdatingPassword(box, true); |
| 102 | + // push the new password into the BoundPassword property |
| 103 | + SetBoundPassword(box, box.Password); |
| 104 | + SetUpdatingPassword(box, false); |
| 105 | + } |
| 106 | + } |
| 107 | +} |
0 commit comments