在MVVM中使用PasswordBox控件
时间:2022-03-14 04:14
在MVVM中使用PasswordBox控件,碰到一个问题。由于**PasswordBox.Password**属性并不是一个依赖属性,所以无法将其作为Binding的目标。# 使用附加属性的解决方案![Password Demo.gif](http://upload-images.jianshu.io/upload_images/140233-dbd415eb4cf9aeb2.gif)**思路:**定义两个依赖属性**Attach**和**AttachPassoword**Attatch为True时,给PasswordBox的PasswordChanged事件添加一个订阅者。在这个订阅者中,利用AttachPassword的Set包装器将PasswordBox.Password赋值给这个附加属性。然后在XAML中,使用扩展标记将AttachPassword作为绑定的目标。**数据流:**PasswordBox.Password->AttachedPasswordProperty<->TextBlock.TextProperty;可以发现,这里缺少了一个环节,就是PasswordBox.Password<-AttachedPasswordProperty,这个可以在AttachedPasswordProperty的回调方法中实现。这里注意增加验证机制,既代码中的isUpdating;如果不加这个验证,就会发生环形数据流(严格来说是以PasswordBox.Password为目标的逻辑上的MulitBinnd)!!会导致光标位置出现问题。```csharpusing System.Windows;using System.Windows.Controls;
namespace 密码绑定{ public static class PasswordHelper { private static bool isUpdating = false;
public static readonly DependencyProperty AttachPasswordProperty = DependencyProperty.RegisterAttached("AttachPassword", typeof(string), typeof(PasswordHelper), new PropertyMetadata(string.Empty, OnAttachPasswordPropertyChanged)); public static string GetAttachPassword(DependencyObject obj) { return (string)obj.GetValue(AttachPasswordProperty); } public static void SetAttachPassword(DependencyObject obj, string value) { obj.SetValue(AttachPasswordProperty, value); }
public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached("Attach", typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false, OnAttachPropertyChanged));
public static bool GetAttach(DependencyObject obj) { return (bool)obj.GetValue(AttachProperty); } public static void SetAttach(DependencyObject obj, bool value) { obj.SetValue(AttachProperty, value); }
private static void OnAttachPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { PasswordBox passwordBox = sender as PasswordBox; if (passwordBox == null) return; if ((bool)e.OldValue) passwordBox.PasswordChanged -= PasswordChanged; if ((bool)e.NewValue) passwordBox.PasswordChanged += PasswordChanged; }
private static void OnAttachPasswordPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { if (!isUpdating) { PasswordBox passwordBox = sender as PasswordBox; if (passwordBox == null) return;
passwordBox.Password = (string)e.NewValue; } }
private static void PasswordChanged(object sender, RoutedEventArgs e) { PasswordBox passwordBox = sender as PasswordBox; isUpdating = true; SetAttachPassword(passwordBox, passwordBox.Password); isUpdating = false; } }}`````` <PasswordBox Grid.Column="1" Margin="5" loc:PasswordHelper.Attach="True" loc:PasswordHelper.AttachPassword="{Binding Text, ElementName=plain, Mode=TwoWay}" > </PasswordBox><TextBlock Name="plain" Grid.Row="1" Grid.Column="1" Margin="5"></TextBlock><Button ...></Button>```# 风险PasswordBox.Password不依赖化的缘由我想是出于安全性的考虑,而View与ViewModel之间通过DataBinding进行驱动必定能发现端倪。
![snoop.png](http://upload-images.jianshu.io/upload_images/140233-fe479aa7a42370e6.png)(看图不说话)
是否采用这种方案,主要的矛盾源头还是安全性和MVVM~