.net core 将IDataErrorInfo替换为INotifyDataErrorInfo

.net core 将IDataErrorInfo替换为INotifyDataErrorInfo,.net-core,idataerrorinfo,inotifydataerrorinfo,.net Core,Idataerrorinfo,Inotifydataerrorinfo,我有一个名为Person的类,它有两个属性FirstName,LastName,两个构造函数,一个ICommand,以及INotifyPropertyChanged和IDataErrorInfo所需的常用内容: class Person : ObservableCollection<Person>, INotifyPropertyChanged, IDataErrorInfo { string firstName, lastName; #region Propert

我有一个名为
Person
的类,它有两个属性
FirstName
LastName,
两个
构造函数
,一个
ICommand
,以及
INotifyPropertyChanged
IDataErrorInfo
所需的常用内容:

class Person : ObservableCollection<Person>, INotifyPropertyChanged, IDataErrorInfo
{
    string firstName, lastName;

    #region Properties
    [Required(ErrorMessage = "First Name is Required")]
    [RegularExpression("test", ErrorMessage = "It's to be test")]
    public string FirstName {
        get => firstName;
        set { firstName = value; OnPropertyChanged(); }
    }

    [Required]
    [RegularExpression("test", ErrorMessage = "It also has to be test")]
    public string LastName {
        get => lastName;
        set { lastName = value; OnPropertyChanged(); }
    }
    #endregion Properties

    #region Constructors
    public Person(){
        AddToList = new Command(CanAdd, Add);
    }

    public Person(string fName, string lName){
        FirstName = fName;
        LastName = lName;
    }
    #endregion Constructors

    #region Command
    public ICommand AddToList { get; set; }
    bool CanAdd(object para) => Validator.TryValidateObject(this, new ValidationContext(this), null, true);
    void Add(object para){
        Add(new Person(FirstName, LastName));
        FirstName = LastName = null;
    }
    #endregion Command

    #region INotifyPropertyChanged
    public new event PropertyChangedEventHandler PropertyChanged;
    void OnPropertyChanged([CallerMemberName] string name = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    #endregion INotifyPropertyChanged

    #region IDataErrorInfo
    public string Error => null;
    public string this[string columnName] {
        get {
            var ValidationResults = new List<ValidationResult>();
            if (Validator.TryValidateProperty(
                    GetType().GetProperty(columnName).GetValue(this),
                    new ValidationContext(this) { MemberName = columnName },
                    ValidationResults
                )) return null;

            return ValidationResults.First().ErrorMessage;
        }
    }
    #endregion IDataErrorInfo
}

它可以工作,如果名字和姓氏无效,我会收到错误消息,只要名字和姓氏无效,按钮就会保持禁用状态。我只想将
IDataErrorInfo
部分替换为
INotifyDataErrorInfo
。我必须在
Person
类和
xaml
中进行哪些更改才能保持相同的功能?

每次引发
ErrorsChanged
事件时,框架都会调用
GetErrors
。由于有一个
hasrerrors
属性,每当出现任何验证错误时,该属性应返回
true
,因此在属性设置器中进行验证并将验证错误缓存在
字典中是有意义的

请参考以下示例实现:

class Person : ObservableCollection<Person>, INotifyPropertyChanged, INotifyDataErrorInfo
{
    string firstName, lastName;

    #region Properties
    [Required(ErrorMessage = "First Name is Required")]
    [RegularExpression("test", ErrorMessage = "It's to be test")]
    public string FirstName
    {
        get => firstName;
        set { firstName = value; OnPropertyChanged(); Validate(); }
    }

    [Required]
    [RegularExpression("test", ErrorMessage = "It also has to be test")]
    public string LastName
    {
        get => lastName;
        set { lastName = value; OnPropertyChanged(); Validate(); }
    }
    #endregion Properties

    #region Constructors
    public Person()
    {
        AddToList = new Command(CanAdd, Add);
        Validate(nameof(FirstName));
        Validate(nameof(LastName));
    }

    public Person(string fName, string lName)
    {
        FirstName = fName;
        LastName = lName;
    }
    #endregion Constructors

    #region Command
    public ICommand AddToList { get; set; }
    bool CanAdd(object para) => _validationResults.Count == 0;
    void Add(object para)
    {
        base.Add(new Person(FirstName, LastName));
        FirstName = LastName = null;
    }
    #endregion Command

    #region INotifyPropertyChanged
    public new event PropertyChangedEventHandler PropertyChanged;
    void OnPropertyChanged([CallerMemberName] string name = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    #endregion INotifyPropertyChanged

    #region INotifyDataErrorInfo
    private readonly Dictionary<string, List<ValidationResult>> _validationResults = new Dictionary<string, List<ValidationResult>>();

    public bool HasErrors => _validationResults.Count > 0;

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    public System.Collections.IEnumerable GetErrors(string propertyName)
    {
        if (_validationResults.TryGetValue(propertyName, out List<ValidationResult> validationResults))
            return new string[1] { validationResults.First().ErrorMessage };
        return null;
    }

    private void Validate([CallerMemberName]string propertyName = "")
    {
        var ValidationResults = new List<ValidationResult>();
        if (Validator.TryValidateProperty(typeof(Person).GetProperty(propertyName).GetValue(this),
                new ValidationContext(this) { MemberName = propertyName }, ValidationResults))
        {
            _validationResults.Remove(propertyName);
        }
        else
        {
            _validationResults[propertyName] = ValidationResults;
        }
        ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
    }
    #endregion
}
类人员:ObservableCollection、INotifyPropertyChanged、INotifyDataErrorInfo
{
字符串firstName,lastName;
#区域属性
[必需(ErrorMessage=“需要名字”)]
[RegularExpression(“test”,ErrorMessage=“待测试”)]
公共字符串名
{
get=>firstName;
设置{firstName=value;OnPropertyChanged();Validate();}
}
[必需]
[RegularExpression(“test”,ErrorMessage=“它也必须被测试”)]
公共字符串姓氏
{
get=>lastName;
设置{lastName=value;OnPropertyChanged();Validate();}
}
#端域属性
#区域构造函数
公众人士()
{
AddToList=新命令(CanAdd,Add);
验证(名字(名字));
验证(nameof(LastName));
}
公众人物(字符串fName,字符串lName)
{
FirstName=fName;
LastName=lName;
}
#端域构造函数
#地区司令部
公共ICommand AddToList{get;set;}
bool CanAdd(对象参数)=>\u validationResults.Count==0;
无效添加(对象段)
{
base.Add(新人物(名字、姓氏));
FirstName=LastName=null;
}
#endregion命令
#区域inotifyproperty已更改
公共新事件属性ChangedEventHandler属性Changed;
void OnPropertyChanged([CallerMemberName]string name=”“)=>PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(名称));
#endregion InotifyProperty已更改
#区域INotifyDataErrorInfo
专用只读词典_validationResults=new Dictionary();
public bool HasErrors=>\u validationResults.Count>0;
公共事件事件处理程序错误更改;
public System.Collections.IEnumerable GetErrors(字符串propertyName)
{
if(_validationResults.TryGetValue(propertyName,out List validationResults))
返回新字符串[1]{validationResults.First().ErrorMessage};
返回null;
}
私有void验证([CallerMemberName]字符串propertyName=”“)
{
var ValidationResults=新列表();
if(Validator.TryValidateProperty)(typeof(Person).GetProperty(propertyName).GetValue)(this),
新的ValidationContext(this{MemberName=propertyName},ValidationResults))
{
_validationResults.Remove(propertyName);
}
其他的
{
_validationResults[propertyName]=validationResults;
}
ErrorsChanged?.Invoke(这是新的DataErrorsChangedEventArgs(propertyName));
}
#端区
}

不知道它是否好,但如果我只是用以下内容替换
IDataErrorInfo
区域:

#region IDataErrorInfo
public bool HasErrors => true;
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public IEnumerable GetErrors(string propertyName)
{
    var ValidationResults = new List<ValidationResult>();
    if (Validator.TryValidateProperty(GetType().GetProperty(propertyName).GetValue(this),
            new ValidationContext(this) { MemberName = propertyName }, ValidationResults))
        return null;

    return new string[1] { ValidationResults.First().ErrorMessage };
}
#endregion IDataErrorInfo
#地区IDataErrorInfo
公共bool hasrerrors=>true;
公共事件事件处理程序错误更改;
公共IEnumerable GetErrors(字符串propertyName)
{
var ValidationResults=新列表();
if(Validator.TryValidateProperty(GetType().GetProperty(propertyName).GetValue)(this),
新的ValidationContext(this{MemberName=propertyName},ValidationResults))
返回null;
返回新字符串[1]{ValidationResults.First().ErrorMessage};
}
#IDataErrorInfo端区

不要触摸任何其他部件,它也可以工作

它比IDataErrorInfo更复杂!使用此实现,您的模型始终处于错误状态,因为
hasrerrors
始终返回
true
@mm8,只要我在
TextBox
两个
文本框中都键入
test
,错误就会消失,按钮状态也会改变,但是
hasrerrors
属性仍然返回
true
,从纯实现的角度来看,这很奇怪。@mm8,在
GetErrors
之外声明
ValidationResults
ValidationResults.Count>0
hasrerrors
中声明可能会解决问题,对吗?请参阅我的答案以获取示例。
#region IDataErrorInfo
public bool HasErrors => true;
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public IEnumerable GetErrors(string propertyName)
{
    var ValidationResults = new List<ValidationResult>();
    if (Validator.TryValidateProperty(GetType().GetProperty(propertyName).GetValue(this),
            new ValidationContext(this) { MemberName = propertyName }, ValidationResults))
        return null;

    return new string[1] { ValidationResults.First().ErrorMessage };
}
#endregion IDataErrorInfo