Почему мой ConvertBack не вызывается, WPF Converter & ValidationRule? - PullRequest
2 голосов
/ 14 февраля 2011

Я пытаюсь связать текстовое поле, которое может проверять адреса электронной почты, разделенные на ',' или ';'. Цель состоит в том, чтобы иметь флажок, текстовое поле и кнопку на странице. Если флажок установлен, то пользователь должен ввести действующий адрес электронной почты, иначе кнопка должна быть отключена. Если checdkbox не нажимается, значит, кнопка должна быть включена. Я иду по кругу с этим, не могли бы вы помочь?

Пожалуйста, найдите мою структуру ViewModel ниже:

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>

Также я устанавливаю свой текстовый текст, как показано ниже, в конструкторе моей страницы xaml.

 public EMailValidatorWindow()
        {
            InitializeComponent();

            DataContext = new EmailValidatorViewModel();
        }

Вот мой электронный валидатор:

    public class EmailValidationRule:ValidationRule
        {
            private const string EmailRegEx = @"\b[A-Z0-9._%-]+@[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;
        }
    }

1 Ответ

4 голосов
/ 14 февраля 2011

Попробуйте установить UpdateSourceTrigger в PropertyChanged в привязке вашего текстового поля.

<Binding UpdateSourceTrigger="PropertyChanged"  Path="OtherRecipients" Mode="TwoWay" Converter="{StaticResource ListToStringConverter}" NotifyOnSourceUpdated="True"> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...