IDataErrorInfo 的索引器在向 (int)-Textbox 发送短信时不会引发

Indexer of IDataErrorInfo doesn't raise while texting to an (int)-Textbox

我无法检查用户是否将一些文本设置到绑定到整数值的文本框中。如果用户设置数字一切正常。如果是负数,文本框外会出现红色边框,并且 OK 按钮会变灰。如果他在文本框中设置文本,文本框也是红色的,但确定按钮不会变灰。

我得到了以下文本框和按钮

<TextBox Text="{Binding ObjectModel.Length, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" x:Name="textBox_Length" />

<Button x:Name="button_applyChanges" Content="Speichern" Command="{Binding ObjectModel.OkCommand}" />

我的模型如下:

public class ObjectModel : BaseModel
{
    [Required(AllowEmptyStrings = false, ErrorMessage = "{0} can't be empty.")]
    [Range(typeof(Decimal), "0", "100000000", ErrorMessage = "{0} must be a decimal/number between {1} and {2}.")]
    public int Length { get; set; }

    public RelayCommand OkCommand { get; private set; }

    protected override void InitCommands()
    {
        base.InitCommands();
        OkCommand = new RelayCommand(
            () =>
            {
                Trace.WriteLine("OK");
            },
            () => IsOk);
    }

    protected override void OnErrorsCollected()
    {
        base.OnErrorsCollected();
        OkCommand.RaiseCanExecuteChanged();
    }
}

在基本模型中,我包括了 IDataErrorInfo 和 INotifyPropertyChanged。我获得了以下用于索引器调用的方法,但索引器调用不会在文本输入时引发...

    public virtual string this[string columnName]
    {
        get
        {
            CollectErrors();
            return Errors.ContainsKey(columnName) ? Errors[columnName] : string.Empty;
        }
    }

    private void CollectErrors()
    {
        Errors.Clear();
        PropertyInfos.ForEach(
            prop =>
            {
                var currentValue = prop.GetValue(this);
                var requiredAttr = prop.GetCustomAttribute<RequiredAttribute>();
                var maxLenAttr = prop.GetCustomAttribute<MaxLengthAttribute>();
                var numericAttr = prop.GetCustomAttribute<RangeAttribute>();

                if (requiredAttr != null)
                    if (string.IsNullOrEmpty(currentValue?.ToString() ?? string.Empty))
                        Errors.Add(prop.Name, requiredAttr.ErrorMessage);

                if (maxLenAttr != null)
                    if ((currentValue?.ToString() ?? string.Empty).Length > maxLenAttr.Length)
                        Errors.Add(prop.Name, maxLenAttr.ErrorMessage);

                if (numericAttr != null)
                {
                    var result = 0;
                    var resultBool = Int32.TryParse(currentValue.ToString(), out result);

                        if(result <= 0 || !resultBool)
                            Errors.Add(prop.Name, numericAttr.ErrorMessage);
                }
                // further attributes
            });
        // we have to this because the Dictionary does not implement INotifyPropertyChanged            
        OnPropertyChanged(nameof(HasErrors));
        OnPropertyChanged(nameof(IsOk));
        // commands do not recognize property changes automatically
        OnErrorsCollected();
    }

我希望当用户将文本输入文本框时按钮变灰。

所以,我终于找到了解决方案...我将 Length-type 更改为字符串并使用正则表达式解决了它。

对象模型:

    [RegularExpression("([1-9][0-9]*)", ErrorMessage = "Must be a positive number")]
    public string Length { get; set; }

基本模型的新 CollectErrors() 方法:

    private void CollectErrors()
    {
        Errors.Clear();
        PropertyInfos.ForEach(
            prop =>
            {
                var currentValue = prop.GetValue(this);
                var requiredAttr = prop.GetCustomAttribute<RequiredAttribute>();
                var maxLenAttr = prop.GetCustomAttribute<MaxLengthAttribute>();
                var regexAttr = prop.GetCustomAttribute<RegularExpressionAttribute>();

                if (requiredAttr != null)
                    if (string.IsNullOrEmpty(currentValue?.ToString() ?? string.Empty))
                        Errors.Add(prop.Name, requiredAttr.ErrorMessage);

                if (maxLenAttr != null)
                    if ((currentValue?.ToString() ?? string.Empty).Length > maxLenAttr.Length)
                        Errors.Add(prop.Name, maxLenAttr.ErrorMessage);

                if (regexAttr != null)
                    if (!regexAttr.IsValid((currentValue?.ToString() ?? string.Empty)))
                        Errors.Add(prop.Name, regexAttr.ErrorMessage);
            });
        OnPropertyChanged(nameof(HasErrors));
        OnPropertyChanged(nameof(IsOk));
        OnErrorsCollected();
    }