Last active
June 13, 2024 11:49
-
-
Save cbalioglu/64dda0744ea63bd7d8dc to your computer and use it in GitHub Desktop.
An Expression Blend behavior for WPF that enables binding to the Password property of the PasswordBox control.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Windows; | |
using System.Windows.Controls; | |
using System.Windows.Data; | |
using System.Windows.Interactivity; | |
namespace Balioglu | |
{ | |
// USAGE: | |
// | |
//<PasswordBox> | |
// <blend:Interaction.Behaviors> | |
// <l:PasswordBoxBehavior UpdateSourceTrigger="PropertyChanged" | |
// Binding="{Binding Source={StaticResource MyViewModel},Path=Password}" /> | |
// </blend:Interaction.Behaviors> | |
//</PasswordBox> | |
// | |
/// <summary> | |
/// Enables binding to the <see cref="Password" /> property of the <see cref="PasswordBox" /> control. | |
/// </summary> | |
/// <remarks> | |
/// Note that storing plain text passwords in memory is a security risk. You should avoid using this solution | |
/// unless it is absolutely necessary to use the MVVM pattern. | |
/// </remarks> | |
public sealed class PasswordBoxBehavior : Behavior<PasswordBox> | |
{ | |
public static readonly DependencyProperty BindingProperty = | |
DependencyProperty.Register("Binding", typeof(String), typeof(PasswordBoxBehavior), | |
new FrameworkPropertyMetadata(OnBindingChanged) { BindsTwoWayByDefault = true }); | |
public static readonly DependencyProperty UpdateSourceTriggerProperty = | |
DependencyProperty.Register("UpdateSourceTrigger", typeof(UpdateSourceTrigger), typeof(PasswordBoxBehavior), | |
new PropertyMetadata(UpdateSourceTrigger.LostFocus), ValidateUpdateSourceTrigger); | |
/// <summary> | |
/// Gets or sets the password. | |
/// </summary> | |
public String Binding | |
{ | |
get | |
{ | |
return (String) GetValue(BindingProperty); | |
} | |
set | |
{ | |
SetValue(BindingProperty, value); | |
} | |
} | |
/// <summary> | |
/// Gets or sets the timing of binding source updates. | |
/// </summary> | |
public UpdateSourceTrigger UpdateSourceTrigger | |
{ | |
get | |
{ | |
return (UpdateSourceTrigger) GetValue(UpdateSourceTriggerProperty); | |
} | |
set | |
{ | |
SetValue(UpdateSourceTriggerProperty, value); | |
} | |
} | |
private static void OnBindingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |
{ | |
PasswordBoxBehavior behavior = d as PasswordBoxBehavior; | |
if (behavior != null) | |
{ | |
behavior.SetTargetPassword((String) e.NewValue); | |
} | |
} | |
private static Boolean ValidateUpdateSourceTrigger(Object value) | |
{ | |
UpdateSourceTrigger trigger = (UpdateSourceTrigger) value; | |
return | |
trigger == UpdateSourceTrigger.Default || | |
trigger == UpdateSourceTrigger.LostFocus || | |
trigger == UpdateSourceTrigger.PropertyChanged; | |
} | |
private Boolean m_passwordBoxChanged; | |
private Boolean m_isUpdatingBinding; | |
protected override void OnAttached() | |
{ | |
base.OnAttached(); | |
PasswordBox passwordBox = AssociatedObject; | |
passwordBox.PasswordChanged += OnPasswordBoxChanged; | |
passwordBox.LostFocus += OnPasswordBoxLostFocus; | |
passwordBox.SetBinding(Validation.ValidationAdornerSiteForProperty, new Binding { Source = this }); | |
} | |
protected override void OnDetaching() | |
{ | |
base.OnDetaching(); | |
PasswordBox passwordBox = AssociatedObject; | |
passwordBox.PasswordChanged -= OnPasswordBoxChanged; | |
passwordBox.LostFocus -= OnPasswordBoxLostFocus; | |
BindingOperations.ClearBinding(passwordBox, Validation.ValidationAdornerSiteForProperty); | |
} | |
private void SetTargetPassword(String password) | |
{ | |
if (m_isUpdatingBinding) | |
{ | |
return; | |
} | |
PasswordBox passwordBox = AssociatedObject; | |
passwordBox.PasswordChanged -= OnPasswordBoxChanged; | |
passwordBox.Password = password; | |
passwordBox.PasswordChanged += OnPasswordBoxChanged; | |
} | |
private void OnPasswordBoxChanged(Object sender, RoutedEventArgs e) | |
{ | |
if (UpdateSourceTrigger == UpdateSourceTrigger.PropertyChanged) | |
{ | |
UpdateBinding(); | |
} | |
else | |
{ | |
m_passwordBoxChanged = true; | |
} | |
} | |
private void OnPasswordBoxLostFocus(Object sender, RoutedEventArgs e) | |
{ | |
if (UpdateSourceTrigger == UpdateSourceTrigger.PropertyChanged || !m_passwordBoxChanged) | |
{ | |
return; | |
} | |
UpdateBinding(); | |
m_passwordBoxChanged = false; | |
} | |
private void UpdateBinding() | |
{ | |
m_isUpdatingBinding = true; | |
Binding = AssociatedObject.Password; | |
m_isUpdatingBinding = false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment