UserControl中的PasswordBox-DataBinding有效,但框看起来是空的



最新信息/问题:下面发布的所有内容都有效(绑定PasswordBox字符串的数据),除了我的PasswordBox看起来是空的,即使它的内容是正确的。

详细信息:我有一个带有PasswordBox和DependencyProperty的UserControl。该DP可用于通过数据绑定从该PWBox设置/检索SecureString。

public partial class PasswordUserControl : UserControl
{       
public SecureString Password
{
get { return (SecureString)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
// https://msdn.microsoft.com/en-us/library/ms750428(v=vs.110).aspx
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(SecureString), typeof(PasswordUserControl),
new PropertyMetadata(default(SecureString)));
public PasswordUserControl()
{
InitializeComponent();
PasswordEntryBox.PasswordChanged += (sender, args) => {
Password = ((PasswordBox)sender).SecurePassword; };
}       
}

简单XAML:

<UserControl x:Class="WpfClient.PasswordUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:local="clr-namespace:WpfClient"
mc:Ignorable="d" 
d:SizeToContent="true">
<StackPanel>
<DockPanel>
<Label Content="Password" Margin="0,0,5,0" DockPanel.Dock="Left"/>
<PasswordBox Name="PasswordEntryBox" Width="200" DockPanel.Dock="Right" />
</DockPanel>
</StackPanel>

在另一个位置简单使用该控件:

<local:PasswordUserControl Password="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

"绑定密码"感觉进入SecureString:

public SecureString Password
{
get { return m_Password; }
set
{
m_Password = value;
RaisePropertyChanged("Password");
}
}

问题:数据绑定似乎是双向的;我得到了正确的用户输入(触发登录有效)。PropertyChanged也起作用:对于添加的每个字符,我都会得到一个属性更新。

不起作用的是:实际的PasswordBox看起来是空的。如果我先在代码中设置Password并查看控件,它不会为已经输入的数据绑定文本显示一堆匿名圆圈字符(但字符串本身是正确的——调试器会这么说,实际登录有效!)。如果我手动在框中输入密码文本,我确实会得到匿名字符作为输入,但我的输入不会添加到所谓的数据绑定的现有字符串中。它似乎擦除了数据绑定字符串,并从头开始创建一个新字符串。

我做错了什么?

要想查看PasswordBox中的任何密码字符,需要将其Password属性设置为string。这意味着您需要从SecureString对象中提取纯密码字符串。

只要Password依赖项属性设置为新的SecureString值,就应该执行此操作。

您可以将PropertyChangedCallback添加到依赖属性中,并按如下方式实现UserControl

public partial class PasswordUserControl : UserControl
{
public SecureString Password
{
get { return (SecureString)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(SecureString), typeof(PasswordUserControl),
new PropertyMetadata(default(SecureString), new PropertyChangedCallback(OnPasswordChanged)));

public PasswordUserControl()
{
InitializeComponent();
PasswordEntryBox.PasswordChanged += PasswordEntryBox_PasswordChanged;
}
private bool _handleEvent = true;
private void PasswordEntryBox_PasswordChanged(object sender, RoutedEventArgs e)
{
if(_handleEvent)
Password = ((PasswordBox)sender).SecurePassword;
}
private static void OnPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SecureString ss = e.NewValue as SecureString;
if(ss != null)
{
PasswordUserControl control = d as PasswordUserControl;
if(control != null)
{
control._handleEvent = false;
control.PasswordEntryBox.Password = ConvertToUnsecureString(ss);
control._handleEvent = true;
}
}
}
public static string ConvertToUnsecureString(SecureString securePassword)
{
if (securePassword == null)
throw new ArgumentNullException("securePassword");
IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
}

LoginPassword.Password = Globals.credentials == null ? "": new NetworkCredential("", Globals.credentials.SecurePassword).Password;

只需在xaml.cs文件中放一行即可。将密码框命名为"登录密码"。

相关内容

  • 没有找到相关文章

最新更新