WPF 重复密码 IMultiValueConverter

WPF Repeat password IMultiValueConverter

我想要一个 PasswordBox 和另一个 PasswordBox 来重复选择的密码和一个提交按钮。

这是我得到的:

WPF:

<UserControl.Resources>
    <converter:PasswordConverter x:Key="PasswdConv"/>
</UserControl.Resources>


<PasswordBox PasswordChar="*" Name="pb1"/>
<PasswordBox PasswordChar="*" Name="pb2"/>
<Button Content="Submit" Command="{Binding ChangePassword}">
    <Button.CommandParameter>
        <MultiBinding Converter="{StaticResource PasswdConv}">
            <MultiBinding.Bindings>
                <Binding ElementName="pb1"/>
                <Binding ElementName="pb2"/>
            </MultiBinding.Bindings>
        </MultiBinding>
    </Button.CommandParameter>
</Button>

转换器:

public class PasswordConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        List<string> s = values.ToList().ConvertAll(p => SHA512(((PasswordBox)p).Password));
        if (s[0] == s[1])
            return s[0];
        return "|NOMATCH|";
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

命令(更改密码):

if ((p as string) != "|NOMATCH|")
{
    MessageBox.Show("Password changed");
}
else
{
    MessageBox.Show("Passwords not matching");
}

当我在转换器和命令中设置断点时,我得到以下结果: 一旦视图加载,它就会跳入转换器并尝试转换两个 PasswordBoxes。两者都是空的。 当我按下按钮时(两个 PasswordBoxes 中的内容无关紧要)它不会进入转换器并在 command-if 处停止。 P代表空密码。

您的代码中有多个错误需要考虑:

  • 您的绑定是直接绑定到控件元素(在您的例子中是 PasswordBox),您应该始终使用 "Path" 属性绑定到它的 (dep) 属性多次应用绑定以观察值(为什么框架要触发 PropertyChanged 事件?您的控件不会更改,但它们的属性可能会更改)
  • 如果您使用 TextBox 而不是 PasswordBox 并将 Path="Text" 添加到您的绑定,您将获得预期的行为
  • 坏消息:出于安全原因,您无法绑定到 PasswordBox 的密码 属性。

Convert 方法只会在多重绑定的源 属性 发生变化时调用,但您绑定到 PasswordBox 本身并且它永远不会改变。

并且绑定到 Password 属性 也不起作用,因为 PasswordoBox 在 属性 更改时不会引发任何更改通知。

它确实引发了一个 PasswordChanged 事件,所以你可以处理这个并在这个事件处理程序中设置 CommandParameter 属性 而不是使用转换器:

private void OnPasswordChanged(object sender, RoutedEventArgs e)
{
    string password = "|NOMATCH|";
    List<PasswordBox> pb = new List<PasswordBox>(2) { };
    List<string> s = new List<string>[2] { SHA512(pb1.Password), SHA512(pb2.Password) };
    if (s[0] == s[1])
        password = s[0];

    btn.CommandParameter = password;
}

XAML:

<PasswordBox PasswordChar="*" Name="pb1" PasswordChanged="OnPasswordChanged"/>
<PasswordBox PasswordChar="*" Name="pb2" PasswordChanged="OnPasswordChanged"/>
<Button x:Name="btn" Content="Submit" Command="{Binding ChangePassword}" />

如果您希望能够跨多个视图和 PasswordBox 控件重用此功能,您应该编写 attached behaviour.