2011-02-14 307 views
2

我试图绑定一个可以验证分割为','或';'的电子邮件地址的文本框,目标是在页面上有一个复选框,一个文本框和一个按钮。如果复选框被选中,那么用户必须输入一个有效的电子邮件地址,否则该按钮必须被禁用。如果checdkbox没有被点击,那么该按钮必须被启用。我将围绕这个圈子转圈,你能帮忙吗?为什么我的ConvertBack没有被调用,WPF Converter&ValidationRule?

请在下面找到我的视图模型结构:

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页面:

<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> 

我也做如下设置我的datacontext在我的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

尝试设置UpdateSourceTrigger在文本框结合 '的PropertyChanged'。

<Binding UpdateSourceTrigger="PropertyChanged" Path="OtherRecipients" Mode="TwoWay" Converter="{StaticResource ListToStringConverter}" NotifyOnSourceUpdated="True"> 
相关问题