c# - 为什么我的 ConvertBack 没有被调用,WPF 转换器和 ValidationRule?

标签 c# wpf binding

我正在尝试绑定(bind)一个文本框,该文本框可以验证由“,”或“;”分隔的电子邮件地址。目标是在页面上有一个复选框、一个文本框和一个按钮。如果选中该复选框,则用户必须输入有效的电子邮件地址,否则必须禁用该按钮。如果未单击 checkkbox,则必须启用该按钮。我正在绕这个问题,您能帮忙吗?

请在下面找到我的 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;
        }
    }

最佳答案

尝试在文本框绑定(bind)中将 UpdateSourceTrigger 设置为“PropertyChanged”。

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

关于c# - 为什么我的 ConvertBack 没有被调用,WPF 转换器和 ValidationRule?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4990180/

相关文章:

c# - 根据特定属性比较两个列表

c# - 基于字符串中存在的整数进行排序

c# - 在 Linux 服务器上远程调试 ASP.NET Core

c# - WPF 直接绑定(bind)到 DataContext

java - boolean 属性如何与 createBooleanBinding 配合使用

javascript - Angula2 输入未绑定(bind)

c# - 构建复杂的条件绑定(bind)的最佳方式

c# - 使用 Caliburn Micro 从 View 模型中的属性名称获取控制权

wpf - 如何在 RibbonApplicationMenu 的顶部设置文本

c# - 夹一个 4 :3 image in WPF with a circle