C# 验证密码和确认密码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18789203/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Validate Password and Confirm Password
提问by user2216584
I have a WPF form which has following controls -
我有一个 WPF 表单,它具有以下控件 -
Name - TextBox
名称 - 文本框
Password - PasswordBox
密码 - 密码框
Confirm Password - PasswordBox
确认密码 - PasswordBox
Save - Button
保存 - 按钮
What is want is - Enable save button only if all controls have valid value
想要的是 - 仅当所有控件都具有有效值时才启用保存按钮
Name should not be empty - To validate this i am using custom ValidationRule
名称不应为空 - 为了验证这一点,我正在使用自定义 ValidationRule
Password should not be empty - To validate this i am using custom ValidationRule
密码不应为空 - 为了验证这一点,我使用自定义 ValidationRule
Password and Confirm password should match.
密码和确认密码应匹配。
I am using ValidationRule because it will not update source in case of error. [I cannot use IDataInfoError].
我正在使用 ValidationRule 因为它不会在出现错误时更新源。[我不能使用 IDataInfoError]。
I am not able validate Password and Confirm Password match condition. Below is my XAML and Code behind -
我无法验证密码和确认密码匹配条件。下面是我的 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>
Code behind C# -
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;
}
}
}
}
}
采纳答案by Sheridan
As I'm not a fan of ValidationRule
s, I can't directly answer your question, but I just wanted to show you that there is a mucheasier way to do this.
因为我不是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;
}
If you really need red borders on your controls when there are errors as well, then you can implement the IDataErrorInfo
interface on your data type classes, eg. Person
.
如果您确实需要在出现错误时在控件上使用红色边框,那么您可以IDataErrorInfo
在数据类型类上实现该接口,例如。Person
.
回答by Lai32290
Maybe you can validate those camp with event
也许你可以通过事件来验证那些阵营
<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>
Event:
事件:
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;
}
回答by Adumuah Dowuona
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;
}