验证密码和确认密码
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】:由于我不是ValidationRule
s 的粉丝,因此我无法直接回答您的问题,但我只是想向您展示有一种更更简单的方法可以做到这一点。
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;
【讨论】:
以上是关于验证密码和确认密码的主要内容,如果未能解决你的问题,请参考以下文章