2013-09-13 6 views
0

У меня есть форма WPF, который имеет следующие элементы управления -Подтвердить пароль и Подтверждение пароля

Имя - TextBox

Пароль - PasswordBox

Confirm Password - PasswordBox

Сохранить - Кнопка

Что нужно - Включить кнопку сохранения, только если все элементы управления имеют действительное значение

Имя не должно быть пустым - Чтобы проверить это, я использую пользовательский 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;     
     } 
    }   
} 

}

+0

Надежды http://stackoverflow.com/questions/5960107/wpf-validation-confirmed-password?rq=1 могут помочь немного. – Eben

ответ

0

Как я не поклонник ValidationRule с, я не могу сразу ответить на ваш вопрос, но я просто хотел показать вам, что есть много простой способ сделать это.

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.

+0

Большое спасибо за руководство. Я буду использовать IDataErrorInfo. – user2216584

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; 
} 
+0

Спасибо, что направил меня в этом отношении :) – user2216584

0
if (txtpassword1.Text == "" || txtpassword2.Text == "") 
     { 
      MessageBox.Show("Please enter values"); 
      txtpassword1.Focus(); 
      return; 
     } 
     if (txtpassword1.Text != txtpassword2.Text) 
     { 
      MessageBox.Show("Password not matching"); 
      txtpassword2.Focus(); 
      return; 
     } 
Смежные вопросы