2011-02-14 4 views
2

','또는 ';'로 분리 된 이메일 주소의 유효성을 검사 할 수있는 텍스트 상자를 바인딩하려고합니다. 확인란의 선택은 체크 박스, 텍스트 상자 및 버튼을 페이지에 표시하는 것입니다. 확인란을 선택하면 사용자가 유효한 이메일 주소를 입력해야합니다. 그렇지 않으면 버튼을 비활성화해야합니다. checdkbox가 클릭되지 않으면 버튼이 활성화되어 있어야합니다.이 동그라미로 돌아갈 것입니다. 도움을받을 수 있습니까?ConvertBack이 호출되지 않는 이유는 무엇입니까? WPF 변환기 및 ValidationRule?

<Window x:Class="EMailValidator.EMailValidatorWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:EMailValidator="clr-namespace:EMailValidator" Title="Window1" Height="300" Width="300"> 
    <Window.Resources>     
     <Style x:Key="ToolTipBound" TargetType="TextBox"> 
      <Setter Property="Foreground" Value="#333333" /> 
      <Setter Property="MaxLength" Value="40" /> 
      <Setter Property="Width" Value="392" /> 
      <Style.Triggers> 
       <Trigger Property="Validation.HasError" Value="true"> 
        <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, 
         Path=(Validation.Errors)[0].ErrorContent}"/> 
       </Trigger> 
       <Trigger Property="IsEnabled" Value="false"> 
        <Setter Property="Text" Value=""/> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
     <EMailValidator:ListToStringConverter x:Key="ListToStringConverter" /> 
    </Window.Resources> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="20"></RowDefinition> 
      <RowDefinition Height="20"></RowDefinition> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto"/> 
      <ColumnDefinition/> 
     </Grid.ColumnDefinitions> 
     <CheckBox Margin="15,0,0,0" x:Name="OthersCheckbox" Grid.Row="2" Grid.Column="0" Unchecked="OnOthersCheckboxUnChecked" IsChecked="{Binding Path=IsChecked}">Others</CheckBox> 
     <TextBox Margin="5,0,5,0" x:Name="OtherRecipientsTextBox" Grid.Row="2" Grid.Column="1" IsEnabled="{Binding ElementName=OthersCheckbox, Path=IsChecked}" Style="{StaticResource ToolTipBound}"> 
      <TextBox.Text> 
       <Binding Path="OtherRecipients" Mode="TwoWay" Converter="{StaticResource ListToStringConverter}" NotifyOnSourceUpdated="True"> 
        <Binding.ValidationRules> 
         <EMailValidator:EmailValidationRule/> 
        </Binding.ValidationRules> 
       </Binding> 
      </TextBox.Text> 

     </TextBox> 
     <Button x:Name="OkButton" Grid.Row="3" Grid.Column="0" Command="{Binding OnOkCommand}">Ok</Button> 
    </Grid> 
</Window> 

이 또한 내 XAML 페이지의 생성자에서 다음과 같이 내 데이터 컨텍스트를 설정하십시오

public class EmailValidatorViewModel : DependencyObject 
    { 
     public EmailValidatorViewModel() 
     { 
      OnOkCommand = new DelegateCommand<object>(vm => OnOk(), vm => CanEnable()); 
      OtherRecipients = new List<string>(); 
     } 

     private bool CanEnable() 
     { 
      return !IsChecked || HasOtherRecipients() ; 
     } 

     public static readonly DependencyProperty OtherRecipientsProperty = 
      DependencyProperty.Register("OtherRecipients", typeof(List<string>), typeof(EmailValidatorViewModel)); 


     public List<string> OtherRecipients 
     { 
      get { return (List<string>)GetValue(OtherRecipientsProperty); } 

      set 
      { 
       SetValue(OtherRecipientsProperty, value); 
      } 
     } 


     public bool IsChecked { get; set; } 

     public void OnOk() 
     { 
      var count = OtherRecipients.Count; 
     } 

     public bool HasOtherRecipients() 
     { 
      return OtherRecipients.Count != 0; 
     } 

     public DelegateCommand<object> OnOkCommand { get; set; } 

    } 

는 또한 아래에있는 내 XAML 페이지입니다 :

아래에있는 내 뷰 모델 구조를 검색 할 수 있습니다.

public EMailValidatorWindow() 
     { 
      InitializeComponent(); 

      DataContext = new EmailValidatorViewModel(); 
     } 

여기 내 이메일 검사기입니다 :

public class EmailValidationRule:ValidationRule 
     { 
      private const string EmailRegEx = @"\b[A-Z0-9._%-][email protected][A-Z0-9.-]+\.[A-Z]{2,4}\b"; 

      private readonly Regex regEx = new Regex(EmailRegEx,RegexOptions.IgnoreCase); 

      public override ValidationResult Validate(object value, CultureInfo cultureInfo) 
      { 
       var inputAddresses = value as string; 

       if(inputAddresses == null) 
        return new ValidationResult(false,"An unspecified error occured while validating the input.Are you sure that you have entered a valid EMail address?"); 

       var list = inputAddresses.Split(new[] {';',','}); 

       var failures = list.Where(item => !regEx.Match(item).Success); 

       if(failures.Count() <= 0) 
        return new ValidationResult(true,null); 

       var getInvalidAddresses = string.Join(",", failures.ToArray()); 

       return new ValidationResult(false,"The following E-mail addresses are not valid:"+getInvalidAddresses+". Are you sure that you have entered a valid address seperated by a semi-colon(;)?."); 
      } 

...and my converter: 

public class ListToStringConverter:IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 

      var input = value as List<string>; 

      if (input.Count == 0) 
       return string.Empty; 

      var output = string.Join(";", input.ToArray()); 

      return output; 

     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      var input = value as string; 

      if (string.IsNullOrEmpty(input)) 
       return new List<string>(); 

      var list = input.Split(new[] { ';' }); 

      return list; 
     } 
    } 

답변

4

당신의 텍스트 상자 바인딩에 '하여 PropertyChanged'하는 UpdateSourceTrigger을 설정하십시오.

<Binding UpdateSourceTrigger="PropertyChanged" Path="OtherRecipients" Mode="TwoWay" Converter="{StaticResource ListToStringConverter}" NotifyOnSourceUpdated="True"> 
관련 문제