验证密码和确认密码

Posted

技术标签:

【中文标题】验证密码和确认密码【英文标题】:Validate Password and Confirm Password 【发布时间】:2013-09-18 07:29:03 【问题描述】:

我有一个 WPF 表单,其中包含以下控件 -

名称 - 文本框

密码 - 密码框

确认密码 - 密码框

保存 - 按钮

需要的是 - 仅当所有控件都具有有效值时才启用保存按钮

名称不应为空 - 为了验证这一点,我正在使用自定义 ValidationRule

密码不应为空 - 为了验证这一点,我正在使用自定义 ValidationRule

密码和确认密码应该匹配。

我正在使用 ValidationRule,因为它不会在出现错误时更新源。 [我无法使用 IDataInfoError]。

我无法匹配条件。下面是我的 XAML 和背后的代码 -

<Window x:Class="WPFPasswordValidation.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPFPasswordValidation"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <ResourceDictionary>            
        <ControlTemplate x:Key="validationTemplate">
            <DockPanel>
                <Border BorderBrush="Red" BorderThickness="1">
                    <AdornedElementPlaceholder/>
                </Border>
            </DockPanel>
        </ControlTemplate>
        <Style x:Key="textBoxInError" TargetType="x:Type TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip"
          Value="Binding RelativeSource=x:Static RelativeSource.Self,
                          Path=(Validation.Errors)[0].ErrorContent"/>
                </Trigger>
            </Style.Triggers>
        </Style>
        <Style x:Key="passwordBoxInError" TargetType="x:Type PasswordBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip"
          Value="Binding RelativeSource=x:Static RelativeSource.Self,
                          Path=(Validation.Errors)[0].ErrorContent"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </ResourceDictionary>

</Window.Resources>
<Grid>
    <TextBox Name="txtName" HorizontalAlignment="Left" Height="23" Margin="155,31,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Validation.Error="Validation_Error" Style="StaticResource textBoxInError" Validation.ErrorTemplate="StaticResource validationTemplate">
        <TextBox.Text>
            <Binding Path="Name" UpdateSourceTrigger="Explicit" NotifyOnValidationError="true" Mode="TwoWay">
                <Binding.ValidationRules>
                    <local:StringRangeValidationRule MinimumLength="1" MaximumLength="30" 
                                    ErrorMessage="Name is required and must be less than 30 letters."/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>
    </TextBox>
    <PasswordBox HorizontalAlignment="Left" Margin="155,128,0,0" VerticalAlignment="Top" Width="120" Name="txtConfirmPass"/>
    <TextBlock HorizontalAlignment="Left" Margin="106,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top"><Run Text="Name"/></TextBlock>
    <PasswordBox Name="txtPassword" HorizontalAlignment="Left" Margin="155,85,0,0" VerticalAlignment="Top" Width="120" PasswordChar="*" local:PasswordBoxAssistant.BindPassword="true" Validation.Error="Validation_Error" Style="StaticResource passwordBoxInError" Validation.ErrorTemplate="StaticResource validationTemplate">
        <local:PasswordBoxAssistant.BoundPassword>
            <Binding Path="Password" Mode="TwoWay" UpdateSourceTrigger="Explicit" NotifyOnValidationError="true">
                <Binding.ValidationRules>
                    <local:StringRangeValidationRule MinimumLength="1" MaximumLength="30" 
                                    ErrorMessage="Password is required and must be less than 30 letters."/>
                </Binding.ValidationRules>
            </Binding>
        </local:PasswordBoxAssistant.BoundPassword>
    </PasswordBox>
    <TextBlock HorizontalAlignment="Left" Margin="88,85,0,0" TextWrapping="Wrap" Text="Password" VerticalAlignment="Top"/>
    <TextBlock HorizontalAlignment="Left" Margin="42,128,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="20"><Run Text="Confirm Password"/></TextBlock>
    <Button Content="Save" HorizontalAlignment="Left" Margin="169,186,0,0" VerticalAlignment="Top" Width="75" Command="Save">
        <Button.CommandBindings>
            <CommandBinding Command="Save" Executed="Save_Executed" CanExecute="Save_CanExecute"/>
        </Button.CommandBindings>
    </Button>
</Grid>

C# 背后的代码 -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Globalization;

namespace WPFPasswordValidation

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window

    private int _noOfErrors = 0;

    BindingExpression be = null;
    public MainWindow()
    
        InitializeComponent();

        Person p = new Person();
        p.Name = "abc";            
        p.Password = "1234";
        this.DataContext = p;

    

    private void Validation_Error(object sender, ValidationErrorEventArgs e)
    
        if (e.Action == ValidationErrorEventAction.Added)
            _noOfErrors++;
        else
            _noOfErrors--;
    

    private void Save_Executed(object sender, ExecutedRoutedEventArgs e)
    

    

    private void Save_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    

        be = this.txtName.GetBindingExpression(TextBox.TextProperty);
        be.UpdateSource();

        be = this.txtPassword.GetBindingExpression(PasswordBoxAssistant.BoundPassword);
        be.UpdateSource();            

        e.CanExecute = _noOfErrors == 0;
        e.Handled = true;
    


public class StringRangeValidationRule : ValidationRule

    private int _minimumLength = -1;
    private int _maximumLength = -1;
    private string _errorMessage;

    public int MinimumLength
    
        get  return _minimumLength; 
        set  _minimumLength = value; 
    

    public int MaximumLength
    
        get  return _maximumLength; 
        set  _maximumLength = value; 
    

    public string ErrorMessage
    
        get  return _errorMessage; 
        set  _errorMessage = value; 
    

    public override ValidationResult Validate(object value,
        CultureInfo cultureInfo)
    
        ValidationResult result = new ValidationResult(true, null);
        string inputString = (value ?? string.Empty).ToString();
        if (inputString == null)
        
            inputString = string.Empty;
        

        if (inputString.Length < this.MinimumLength ||
               (this.MaximumLength > 0 &&
                inputString.Length > this.MaximumLength))
        
            result = new ValidationResult(false, this.ErrorMessage);
        
        return result;
    


public static class PasswordBoxAssistant

    public static readonly DependencyProperty BoundPassword =
        DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxAssistant), new PropertyMetadata(string.Empty, OnBoundPasswordChanged));

    public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(
        "BindPassword", typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false, OnBindPasswordChanged));

    private static readonly DependencyProperty UpdatingPassword =
        DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false));

    private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    
        PasswordBox box = d as PasswordBox;

        // only handle this event when the property is attached to a PasswordBox
        // and when the BindPassword attached property has been set to true
        if (d == null || !GetBindPassword(d))
        
            return;
        

        // avoid recursive updating by ignoring the box's changed event
        box.PasswordChanged -= HandlePasswordChanged;

        string newPassword = (string)e.NewValue;

        if (!GetUpdatingPassword(box))
        
            box.Password = newPassword;
        

        box.PasswordChanged += HandlePasswordChanged;
    

    private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
    
        // when the BindPassword attached property is set on a PasswordBox,
        // start listening to its PasswordChanged event

        PasswordBox box = dp as PasswordBox;

        if (box == null)
        
            return;
        

        bool wasBound = (bool)(e.OldValue);
        bool needToBind = (bool)(e.NewValue);

        if (wasBound)
        
            box.PasswordChanged -= HandlePasswordChanged;
        

        if (needToBind)
        
            box.PasswordChanged += HandlePasswordChanged;
        
    

    private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
    
        PasswordBox box = sender as PasswordBox;

        // set a flag to indicate that we're updating the password
        SetUpdatingPassword(box, true);
        // push the new password into the BoundPassword property
        SetBoundPassword(box, box.Password);
        SetUpdatingPassword(box, false);
    

    public static void SetBindPassword(DependencyObject dp, bool value)
    
        dp.SetValue(BindPassword, value);
    

    public static bool GetBindPassword(DependencyObject dp)
    
        return (bool)dp.GetValue(BindPassword);
    

    public static string GetBoundPassword(DependencyObject dp)
    
        return (string)dp.GetValue(BoundPassword);
    

    public static void SetBoundPassword(DependencyObject dp, string value)
    
        dp.SetValue(BoundPassword, value);
    

    private static bool GetUpdatingPassword(DependencyObject dp)
    
        return (bool)dp.GetValue(UpdatingPassword);
    

    private static void SetUpdatingPassword(DependencyObject dp, bool value)
    
        dp.SetValue(UpdatingPassword, value);
    


public class Person

    private string _name;        
    private string _password;               

    public string Password
    
        get  return _password; 
        set  _password = value; 
    

    public string Name
    
        get  return _name; 
        set
        
            _name = value;                
        
            

【问题讨论】:

希望***.com/questions/5960107/…能帮上一点忙。 【参考方案1】:

也许您可以通过活动验证这些营地

<Grid>
    <TextBox Name="txtName" TextChanged="Content_TextChanged"/>
    <PasswordBox Name="txtPass" PasswordChar="*" PasswordChanged="Content_TextChanged"/>
    <PasswordBox Name="txtConfirmPass" PasswordChar="*" PasswordChanged="Content_TextChanged"/>
    <Button Name="btSave" Content="Save" IsEnabled="False"/>
</Grid>

事件:

private void Content_TextChanged(object sender, TextChangedEventArgs e)

    if (!txtName.Text.Equals(String.Empty) && txtPass.Password.Equals(txtConfirmPass.Password))
        btSave.IsEnabled = true;
    else
        btSave.IsEnabled = false;

【讨论】:

感谢您在这方面指导我:)【参考方案2】:

由于我不是ValidationRules 的粉丝,因此我无法直接回答您的问题,但我只是想向您展示有一种更简单的方法可以做到这一点。

private void Save_CanExecute(object sender, CanExecuteRoutedEventArgs e)

    Person person = (Person)DataContext;
    e.CanExecute = !string.IsNullOrEmpty(person.Name) && 
        !string.IsNullOrEmpty(person.Password) && 
        !string.IsNullOrEmpty(txtConfirmPass.Text) && 
        txtConfirmPass.Text == person.Password;

如果您确实需要在出现错误时在控件上添加红色边框,那么您可以在数据类型类上实现IDataErrorInfo 接口,例如。 Person.

【讨论】:

非常感谢您指导我。我会考虑使用 IDataErrorInfo。【参考方案3】:
 if (txtpassword1.Text == "" || txtpassword2.Text == "")
        
            MessageBox.Show("Please enter values");
            txtpassword1.Focus();
            return;
        
        else if (txtpassword1.Text != txtpassword2.Text)
        
            MessageBox.Show("Password not matching");
            txtpassword2.Focus();
            return;
        

【讨论】:

以上是关于验证密码和确认密码的主要内容,如果未能解决你的问题,请参考以下文章

在 PHP 中验证密码并确认密码

密码和确认密码字段验证 angular2 反应形式

Spring 3 基于注解的验证:密码和确认密码

是的架构验证密码和确认密码不起作用

在没有 JQuery 的情况下验证密码和确认密码 [关闭]

使用引导验证器验证密码并确认密码字段