2 Stimmen

Warum wird mein ConvertBack nicht aufgerufen, WPF Converter & ValidationRule?

Ich versuche, ein Textfeld zu binden, die E-Mail-Adressen durch ',' oder ';' getrennt validieren kann.Das Ziel ist es, ein Kontrollkästchen, ein Textfeld und eine Schaltfläche auf der Seite zu haben.Wenn das Kontrollkästchen aktiviert ist, dann muss der Benutzer eine gültige E-Mail-Adresse eingeben oder sonst die Schaltfläche deaktiviert werden.Wenn das Kontrollkästchen nicht angeklickt wird, dann muss die Schaltfläche aktiviert werden.Ich gehe im Kreis mit diesem einen, könnten Sie bitte helfen?

Nachstehend finden Sie meine ViewModel-Struktur:

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

    }

Auch unten ist meine XAML-Seite:

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

Auch ich setze meine Datacontext wie unten in den Konstruktor meiner Xaml-Seite.

 public EMailValidatorWindow()
        {
            InitializeComponent();

            DataContext = new EmailValidatorViewModel();
        }

Hier ist mein EMail Validator:

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

5voto

ChrisNel52 Punkte 13507

Versuchen Sie, den UpdateSourceTrigger in Ihrer Textfeldbindung auf "PropertyChanged" zu setzen.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X