首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >当多个属性中的任何一个发生更改时,如何验证这些属性?

当多个属性中的任何一个发生更改时,如何验证这些属性?
EN

Stack Overflow用户
提问于 2011-08-19 20:53:31
回答 4查看 8.9K关注 0票数 23

我有两个日期字段: StartDate和EndDate。StartDate必须早于EndDate。

如果用户将StartDate更改为大于EndDate的值,则该DatePicker周围会出现红色边框,反之亦然。如果用户更改了第二个框,以使日期范围现在是正确的,则第一个框仍具有验证错误。

当两个日期字段中的任何一个发生更改时,如何验证这两个字段?

我正在使用IDataErrorInfo

public string GetValidationError(string propertyName)
{
    switch (propertyName)
    {
        case "StartDate":
            if (StartDate > EndDate)
                s = "Start Date cannot be later than End Date";
            break;

        case "EndDate":
            if (StartDate > EndDate)
                s = "End Date cannot be earlier than Start Date";
            break;
    }

    return s;
}

我不能简单地引发PropertyChange事件,因为当其中一个字段发生更改时,我需要验证这两个字段,因此让它们都为另一个字段引发PropertyChange事件将陷入无限循环。

如果另一个日期返回验证错误,我也不喜欢清除日期字段的想法。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-08-19 22:36:56

最简单的方法是在设置器中为需要验证的两个属性引发一个PropertyChanged通知,如bathineni suggests

private DateTime StartDate
{
    get { return _startDate; }
    set
    {
        if (_startDate != value)
        {
            _startDate = value;
            RaisePropertyChanged("StartDate");
            RaisePropertyChanged("EndDate");
        }
    }
}

private DateTime EndDate
{
    get { return _endDate; }
    set
    {
        if (_endDate!= value)
        {
            _endDate= value;
            RaisePropertyChanged("StartDate");
            RaisePropertyChanged("EndDate");
        }
    }
}

但是,如果这对您不起作用,我想出了一种方法来一起验证一组属性,尽管您的类除了INotifyPropertyChanged之外还必须实现INotifyPropertyChanging (我使用的是EntityFramework,默认情况下它们的类实现了这两个接口)。

可拓方法

public static class ValidationGroup
{
    public delegate string ValidationDelegate(string propertyName);
    public delegate void PropertyChangedDelegate(string propertyName);

    public static void AddValidationGroup<T>(this T obj, 
        List<string> validationGroup, bool validationFlag,
        ValidationDelegate validationDelegate, 
        PropertyChangedDelegate propertyChangedDelegate)
        where T : INotifyPropertyChanged, INotifyPropertyChanging
    {

        // This delegate runs before a PropertyChanged event. If the property
        // being changed exists within the Validation Group, check for validation
        // errors on the other fields in the group. If there is an error with one
        // of them, set a flag to true.
        obj.PropertyChanging += delegate(object sender, PropertyChangingEventArgs e)
        {
            if (validationGroup.Contains(e.PropertyName))
            {
                foreach(var property in validationGroup)
                {
                    if (validationDelegate(property) != null)
                    {
                        validationFlag = true;
                        break;
                    }
                }
            }
        };

        // After the Property gets changed, if another field in this group was
        // invalid prior to the change, then raise the PropertyChanged event for 
        // all other fields in the Validation Group to update them.
        // Also turn flag off so it doesn't get stuck in an infinite loop
        obj.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
        {
            if (validationGroup.Contains(e.PropertyName))
            {
                if (validationFlag && validationDelegate(e.PropertyName) == null)
                {
                    validationFlag = false;
                    foreach(var property in validationGroup)
                    {
                        propertyChangedDelegate(property);
                    }
                }
            }
        };
    }
}

要使用它,请将下面的调用添加到任何类的构造函数中,这些类应该一起验证一组属性。

this.AddValidationGroup(
    new List<string> { "StartDate", "EndDate" },
    GetValidationError, OnPropertyChanged);

我已经在一个验证组中测试了多达3个属性,它似乎工作正常。

票数 17
EN

Stack Overflow用户

发布于 2011-11-09 16:48:13

使用这个技巧,它可以防止它们互相调用OnPropertyChanged:

private bool RPCfromStartDate = false;
private bool RPCfromEndDate = false;

public string this[string columnName]
{
    get 
    {
                string result = null;
                switch (columnName)
                {
                    case "StartDate":
                        if (StartDate.Date >= EndDate.Date)
                        {
                            result = "Start Date cannot be later than End Date";
                        }
                        if (!RPCfromEndDate)
                        {
                            RPCfromStartDate = true;                            
                            OnPropertyChanged("EndDate");
                            RPCfromStartDate = false;
                        } 
                    case "EndDate":
                        if (StartDate.Date >= EndDate.Date)
                        {
                            result = "End Date cannot be earlier than Start Date";
                        }
                        if (!RPCfromStartDate)
                        {
                            RPCfromEndDate = true;                            
                            OnPropertyChanged("StartDate");
                            RPCfromEndDate = false;
                        } 
                        break;
                }
...
票数 2
EN

Stack Overflow用户

发布于 2011-08-19 22:29:40

我通常会将我所有的验证错误添加到一个字典中,并让验证模板通过属性名订阅它。在每个属性更改事件处理程序中,我可以检查任意数量的属性,并根据需要添加或移除它们的验证状态。

查看this answer了解我的实现是什么样子的。很抱歉,它是用VB.NET编写的,但应该相当简单。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7121867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档