多个属性发生变化时,如何验证多个属性? [英] How can I validate multiple properties when any of them changes?

查看:89
本文介绍了多个属性发生变化时,如何验证多个属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have two date fields: StartDate and EndDate. StartDate must be earlier than EndDate.

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

If the user changes the StartDate to something greater than the EndDate, a red border appears around that DatePicker, and vise versa. If the user changes the 2nd box so that the date range is now correct, the 1st box still has the Validation Error.

如何更改两个日期字段中的任何一个?

How can I validate both date fields when either one of them changes?

我正在使用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事件将陷入无限循环.

I cannot simply raise a PropertyChange event because I need to validate both fields when either of them changes, so having both of them raise a PropertyChange event for the other will get stuck in an infinite loop.

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

I also do not like the idea of clearing the Date field if the other date returns a validation error.

推荐答案

最简单的方法是在setter中针对需要验证的两个属性,例如

The simplest way is to raise a PropertyChanged notification for in the setter for both properties that need to be validated like 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");
        }
    }
}

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

However if that doesn't work for you, I figured out one way to validate a group of properties together, although your classes have to implement INotifyPropertyChanging in addition to INotifyPropertyChanged (I'm using EntityFramework and by default their classes implement both interfaces)

扩展方法

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

要使用它,请将以下调用添加到应同时验证一组属性的任何类的构造函数中.

To use it, add the following call to the constructor of any class that should validate a group of properties together.

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

我已经在验证组"中使用多达3个属性对此进行了测试,看来工作正常.

I've tested this with up to 3 properties in a Validation Group and it seems to work OK.

这篇关于多个属性发生变化时,如何验证多个属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆