WPF中Password绑定
目录
前言
在WPF(Windows Presentation Foundation)中,密码框(PasswordBox)默认不支持数据绑定,因为它不是以明文形式存储密码,出于安全考虑。但是,我们可以通过附加属性(Attached Property)或者使用代码后台的方式来实现密码的数据绑定。
LoginWindow.xaml
xmlns:Helper="clr-namespace:DataMaster_PLC.Helpers"
<!-- Password Input -->
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<materialDesign:PackIcon Kind="KeyVariant" VerticalAlignment="Center" Margin="0,0,5,0"/>
<PasswordBox Width="230"
Helper:PasswordBoxHelper.Attach="True"
Helper:PasswordBoxHelper.Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
materialDesign:HintAssist.Hint="Password"
Style="{StaticResource MaterialDesignPasswordBox}"/>
</StackPanel>
PasswordHelper.cs
using System.Windows;
using System.Windows.Controls;
namespace DataMaster_PLC.Helpers {
/// <summary>
/// 提供一个辅助工具,用于使PasswordBox的Password属性能够进行数据绑定。
/// </summary>
public class PasswordBoxHelper {
/// <summary>
/// 注册附加依赖属性"Password",类型为string,当其值改变时触发OnPasswordPropertyChanged方法
/// </summary>
public static readonly DependencyProperty PasswordProperty = DependencyProperty.RegisterAttached(
"Password",
typeof(string),
typeof(PasswordBoxHelper),
new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));
/// <summary>
/// 注册附加依赖属性"Attach",表示是否需要启用密码绑定功能,当其值改变时触发Attach方法
/// </summary>
public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached(
"Attach",
typeof(bool),
typeof(PasswordBoxHelper),
new PropertyMetadata(false, Attach));
/// <summary>
/// 私有静态依赖属性"IsUpdating",用于跟踪PasswordBox密码更新状态
/// </summary>
private static readonly DependencyProperty IsUpdatingProperty = DependencyProperty.RegisterAttached(
"IsUpdating",
typeof(bool), typeof(PasswordBoxHelper));
/// <summary>
/// 设置附加属性"Attach"的值
/// </summary>
public static void SetAttach(DependencyObject dp, bool value) {
dp.SetValue(AttachProperty, value);
}
/// <summary>
/// 取附加属性"Attach"的值
/// </summary>
public static bool GetAttach(DependencyObject dp) {
return (bool)dp.GetValue(AttachProperty);
}
/// <summary>
/// 获取附加属性"Password"的值
/// </summary>
public static string GetPassword(DependencyObject dp) {
return (string)dp.GetValue(PasswordProperty);
}
/// <summary>
/// 置附加属性"Password"的值
/// </summary>
public static void SetPassword(DependencyObject dp, string value) {
dp.SetValue(PasswordProperty, value);
}
/// <summary>
/// 获取附加属性"IsUpdating"的值
/// </summary>
private static bool GetIsUpdating(DependencyObject dp) {
return (bool)dp.GetValue(IsUpdatingProperty);
}
/// <summary>
/// 设置附加属性"IsUpdating"的值
/// </summary>
private static void SetIsUpdating(DependencyObject dp, bool value) {
dp.SetValue(IsUpdatingProperty, value);
}
/// <summary>
/// 当"Password"属性发生变化时调用此方法,同步PasswordBox的实际密码与绑定值
/// </summary>
private static void OnPasswordPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
if (sender is PasswordBox passwordBox) {
passwordBox.PasswordChanged -= PasswordChanged;
// 防止在更新过程中引发无限循环
if (!(bool)GetIsUpdating(passwordBox)) {
passwordBox.Password = (string)e.NewValue;
}
passwordBox.PasswordChanged += PasswordChanged;
}
}
/// <summary>
/// 当"Attach"属性值变化时(即绑定或解绑事件处理程序)调用此方法
/// </summary>
private static void Attach(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
if (sender is not PasswordBox passwordBox)
return;
if ((bool)e.OldValue) {
passwordBox.PasswordChanged -= PasswordChanged;
}
if ((bool)e.NewValue) {
passwordBox.PasswordChanged += PasswordChanged;
}
}
/// <summary>
/// 密码更改事件处理程序,当PasswordBox的密码发生更改时,更新绑定到Password属性的值
/// </summary>
private static void PasswordChanged(object sender, RoutedEventArgs e) {
if (sender is PasswordBox passwordBox) {
SetIsUpdating(passwordBox, true);
SetPassword(passwordBox, passwordBox.Password);
SetIsUpdating(passwordBox, false);
}
}
}
}
LoginViewModel.cs
private string _password = string.Empty;
/// <summary>
/// 密码属性
/// </summary>
public string Password {
get => _password;
set {
_password = value;
OnPropertyChanged(nameof(Password));
}
}
评论已关闭