Подтвердить что ты не робот

Как я могу проверить несколько свойств при изменении любого из них?

У меня есть два поля даты: StartDate и EndDate. StartDate должен быть раньше, чем EndDate.

Если пользователь меняет StartDate на нечто большее, чем EndDate, вокруг этой DatePicker появляется красная рамка и наоборот. Если пользователь меняет второй ящик, чтобы теперь был выбран диапазон дат, в первом поле все еще есть ошибка проверки.

Как я могу проверить оба поля даты, когда один из них изменится?

enter image description here

Я использую 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 для другого, он будет застревать в бесконечном цикле.

Мне также не нравится идея очистки поля Date, если другая дата возвращает ошибку проверки.

4b9b3361

Ответ 1

Самый простой способ - поднять уведомление PropertyChanged в настройщике для обоих свойств, которые должны быть проверены, например banineni предлагает

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 в дополнение к INotifyPropertyChanged (я использую 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 свойствами в группе проверки и, похоже, работает нормально.

Ответ 2

Используйте этот трюк, он предотвращает их вызов 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;
                }
...

Ответ 3

Я обычно добавляю все мои ошибки проверки в словарь и подбираю шаблон подтверждения для этого через имя свойства. В каждом измененном обработчике свойств я могу проверить любое количество свойств и добавить или удалить их статус проверки по мере необходимости.

Отметьте этот ответ, как выглядит моя реализация. Извините, что он находится в VB.NET, но должен быть довольно простым.

Ответ 4

Вы также можете подписаться на обработчик события SelectedDateChanged и обновить необходимую привязку.

BindingExpression expression = datePickerStartDate.GetBindingExpression(DatePicker.SelectedDateProperty);
if (expression != null)
{
    expression.UpdateSource();
}