SetPassword(passwordBox, passwordBox. PasswordBox.SetValue(SettingPasswordProperty, true) Private static void HandlePasswordChanged(object sender, RoutedEventArgs e) PasswordBox.Password = e.NewValue as string PasswordBox.PasswordChanged += HandlePasswordChanged If (!(bool)passwordBox.GetValue(PasswordInitializedProperty)) If this is the initial set (see the comment on PasswordProperty), set ourselves up If ((bool)passwordBox.GetValue(SettingPasswordProperty)) HandlePasswordChanged, then do nothing - we already have the latest value). If we're being called because we set the value of the property we're bound to (from inside Private static void HandleBoundPasswordChanged(DependencyObject dp, DependencyPropert圜hangedEventArgs e) New FrameworkPropertyMetadata(Guid.NewGuid().ToString(), HandleBoundPasswordChanged)ĭefaultUpdateSourceTrigger = UpdateSourceTrigger.LostFocus // Match the default on Binding Public static readonly DependencyProperty PasswordProperty =ĭependencyProperty.RegisterAttached("Password", typeof(string), typeof(Secure), If the binding sets us to a value which we already are, then this doesn't happen. and HandleBoundPasswordChanged will be called, which allows us to set up our event subscription. If we set the initial value to something, it'll be set to something else when the binding kicks in, Public static void SetPassword(DependencyObject obj, string value) Create the IHavePassword interface with one method that returns the password clear text. I know this breaks the MVVM pattern, but you shouldnt ever bind to PasswordBox.Password Attached DP, store your password in the ViewModel or any other similar shenanigans. Return (string)obj.GetValue(PasswordProperty) Dont keep clear text passwords in memory. Public static string GetPassword(DependencyObject obj) Private static readonly DependencyProperty SettingPasswordProperty =ĭependencyProperty.RegisterAttached("SettingPassword", typeof(bool), typeof(Secure), new PropertyMetadata(false)) Private static readonly DependencyProperty PasswordInitializedProperty =ĭependencyProperty.RegisterAttached("PasswordInitialized", typeof(bool), typeof(Secure), new PropertyMetadata(false)) There are a number of ways that people have worked around the issue, either by dropping back to the codebehind or writing magic involving attached properties.īelow is my offering: it allows two-way binding (so that you can update the property that you’ve bound the Password property to, and those updates will be reflected in the UI), and is reasonably succinct. What if an attacker snopping around the RAM of your machine isn’t a viable risk, and you’re only obscuring the password to stop people looking over the user’s shoulder? If this property were bindable, then the password that the user entered would be stored in memory in a number of different places, which constitutes a security risk. This is because the Password property of a PasswordBox is a normal property instead of a DependencyProperty. A ‘Binding’ can only be set on a DependencyProperty of a DependencyObject. While it would make sense to provide the SecurePassword directly from the binding, it always seems to provide an empty value.If you’ve ever tried to write XAML which looks like this: Ī ‘Binding’ cannot be set on the ‘Password’ property of type ‘PasswordBox’. Var credential = new (UserName, password) LoginCancel = new DelegateCommand(o => OnLoginCancel(), (o) => IsLoginVisible) LoginAccept = new DelegateCommand(o => OnLogin(o), (o) => IsLoginVisible) Public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register("Password", typeof(string), typeof(BindablePasswordBox), new PropertyMetadata(string.Empty, OnDependencyPropert圜hanged)) public class BindablePasswordBox : Decorator It registers a Propert圜hangedCallback and updates the PasswordBox's Password when it is called. Below is a modified version of it that works in both directions. It only works in one direction, PasswordBox to PasswordProperty. There is an issue with the BindablePasswordBox.
0 Comments
Leave a Reply. |