通过自定义属性与自定义行为实现Passwordbox的双向绑定-wpf精品免费课程_哔哩哔哩_bilibili
点击关注不迷路,你的关注是我们最大的动力。
原始的passwordbox控件为什么不能实现双向绑定?
因为PasswordBox
的密码值不是通过标准的绑定机制暴露出来的。这是出于安全考虑,以防止密码在绑定过程中被截获。所以我们要通过附加属性和行为的方式来实现
一、创建PasswordBox的附加属性类
在项目中添加一个文件夹common,之后创建一个类 PasswordBoxExt.cs
在里面实现如下代码:
public static class PasswordBoxHelper
{
public static readonly DependencyProperty BindPasswordProperty =
DependencyProperty.RegisterAttached(
"BindPwd",
typeof(string),
typeof(PasswordBoxHelper),
new FrameworkPropertyMetadata(string.Empty, OnBindPasswordChanged));
public static string GetBindPwd(DependencyObject dp)
{
return (string)dp.GetValue(BindPasswordProperty);
}
public static void SetBindPwd(DependencyObject dp, string value)
{
dp.SetValue(BindPasswordProperty, value);
}
public static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = dp as PasswordBox;
if (passwordBox == null) return;
string oldPassword = e.OldValue as string;
string newPassword = e.NewValue as string;
if (passwordBox.Password != newPassword)
{
passwordBox.Password = newPassword;
}
if (passwordBox.Password.Length < 5)
{
MessageBox.Show("密码强度不够");
}
passwordBox.PasswordChanged += PasswordBox_PasswordChanged;
}
static void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
if (passwordBox == null) return;
string password = passwordBox.Password;
SetBindPwd(passwordBox, password);
}
}
二、在应用UI层做如下改动
xmlns:local="clr-namespace:MyAgvLesson.ViewModel"
xmlns:pass="clr-namespace:MyAgvLesson.Common"
注意,这个local的DataContext上一节课是放在了后台隐藏代码里,这里我们还可以把他放在前台。如下
<Window.DataContext>
<local:UserViewModel></local:UserViewModel>
</Window.DataContext>
然后我们就可以对PasswordBox这个控件做如下处理:
<PasswordBox pass:PasswordBoxHelper.BindPwd="{Binding Password, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Height="30" Padding="5" DockPanel.Dock="Top" Margin="0 10 0 0">
这样就可以实现PasswordBox的mvvm下的双向绑定。但是我们在这个属性里做了 passwordBox.PasswordChanged += PasswordBox_PasswordChanged;这个操作,这个其实没有解耦的,所以我们采用行为把他们进行分离。
三、使行Behavior为控件定义自己定义行为
还是在上面那个ext.js里,创建一个类,代码如下:
public class PasswordBehavior: Behavior<PasswordBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PasswordChanged += AssociatedObject_PasswordChanged;
}
private void AssociatedObject_PasswordChanged(object sender, RoutedEventArgs e)
{
var password=e.Source as PasswordBox;
string pwd=PasswordBoxHelper.GetBindPwd(password);
if (pwd != null&& password.Password!=pwd)
{
PasswordBoxHelper.SetBindPwd(password, password.Password);
}
}
protected override void OnDetaching() {
base.OnDetaching();
AssociatedObject.PasswordChanged-= AssociatedObject_PasswordChanged;
}
}
这个继承的Behavior要在Nuget里安装Microsoft.Xaml.Behaviors这个包。
然后在UI里面添加:
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
之后在password里添加:
<PasswordBox pass:PasswordBoxHelper.BindPwd="{Binding Password, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Height="30" Padding="5" DockPanel.Dock="Top" Margin="0 10 0 0">
<i:Interaction.Behaviors>
<pass:PasswordBehavior/>
</i:Interaction.Behaviors>
</PasswordBox>
这样就实现了通过自定义的属性与自定义行为实现了passwordBox的双向绑定了。