S / L 4 & IDataErrorInfo - Как принудительно выполнить повторную проверку элемента управления (при касании связанного элемента управления)

У меня есть два элемента управления, привязанные к свойствам MinCartValue и MaxCartValue. MinCartValue должно быть меньше MaxCartValue. Чтобы выполнить эту проверку, я реализовал интерфейс IDataErrorInfo и выполнил указанную выше проверку в методе this [columnName], если затронуты MinCartValue или MaxCartValue. ValidatesOnDataErrors = True устанавливается в привязке обоих элементов управления. Проверка работает правильно, выделяя каждый элемент управления, когда изменение значения его свойства нарушает правило. Проблема в том, что после того, как элемент управления помечен как недопустимый, если пользователь исправляет проблему, изменяя значение другого элемента управления, первый элемент управления остается помеченным как недопустимый. Это понятно, потому что метод IDataErrorInfo не выполнял проверку свойства первого элемента управления.

Итак, мне нужен способ принудительной повторной проверки свойства №1 (или способ очистки недопустимого состояния) при проверке свойства №2, и наоборот. Я попытался вызвать RaisePropertyChanged в моем методе this [columnName], но он ничего не сделал. Также попытался установить для свойства собственное значение, чтобы попытаться обмануть его, чтобы проверить себя, но снова ничего не происходит.

Спасибо


person Laurence    schedule 13.01.2011    source источник


Ответы (4)


Я бы порекомендовал взглянуть на интерфейс INotifyDataErrorInfo (представленный в Silverlight 4). Он может асинхронно уведомлять, если свойства становятся недействительными, поэтому я думаю, что фреймворк лучше соблюдает это во многих свойствах, а не ожидает, что изменяемое в настоящее время свойство является единственным, срок действия которого может измениться.

person Austin Lamb    schedule 14.01.2011
comment
почему, ну почему INotifyDataErrorInfo не в WPF? Какой полезный интерфейс! - person Siy Williams; 18.02.2011

У меня было два свойства DateTime (DateFrom и DateTo), которые нужно было сравнить друг с другом. В установщиках для этих свойств я просто вызвал событие PropertyChanged как для DateTo, так и для DateFrom. Работал как шарм.

person Scott F    schedule 19.05.2011

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

Похоже, проблема вашего кода зависит от UpdateSourceTrigger по умолчанию, который в случае элементов управления TextBox является их фокусом / расфокусировкой. Вы можете установить в XAML атрибут UpdateSourceTrigger, добавив UpdateSourceTrigger = Explicit к привязке, в которой выполняется проверка. Затем в каждом TextBox (MinCartValue, MaxCartValue) добавьте обработчик события к событию TextChanged.

В коде программной части в обработчике событий вы можете сделать что-то вроде этого:

    private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        TheTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    }

TheTextBox в этом случае будет одним из элементов управления вашей тележкой. Метод UpdateSource () - это способ вручную обновить значение привязки, что должно вызвать вашу проверку. Этот метод обеспечивает привязку к триггеру для обновления значений и повышения свойств, измененных за пределами области по умолчанию (с использованием текста, измененного в фокусе и расфокусировки на TextBox в этом случае).

person avanek    schedule 14.01.2011
comment
Спасибо. Я должен был упомянуть, что использую подход MVVM, при котором код, стоящий за ним, не имеет ссылок на элементы управления XAML. Я хотел бы придерживаться этого, поэтому я ищу способ сделать это, ссылаясь только на свойства объекта, действующего как контекст данных. - person Laurence; 15.01.2011
comment
Да, я не знал, используете ли вы MVVM или нет. Я сам пытаюсь следовать MVVM, но, к сожалению, мне еще не удалось найти хорошего решения этой проблемы с помощью MVVM. - person avanek; 17.01.2011

Вот как я это решил. Скажем, Property1 и Property2 созависимы. Я не знаком с MVVM (пока), но вы, вероятно, расширяете свой класс сущности для реализации IDataErrorInfo. В этом случае вы также можете расширить метод On [Property] Changed и сообщить об изменении созависимого свойства:

partial class YourEntity : IDataErrorInfo
{
    public string this[string columnName]
        {
            //Your validation logic
        }

    public string Error
    {
        //WPF doesn't use it anyway
        get { return string.Empty; }
    }

    partial void OnProperty1Changed() 
    {
        OnPropertyChanging("Property2");
        OnPropertyChanged("Property2");
    }

    partial void OnProperty2Changed()
    {
        OnPropertyChanging("Property1");
        OnPropertyChanged("Property1");
    }
}

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

EDIT2: похоже, вы должны использовать OnPropertyChang * вместо ReportPropertyChang *. ReportPropertyChanged уведомит платформу сущности о наличии ожидающих изменений в модели, но на самом деле все, что вы пытаетесь сделать, это проинформировать представление. Вы не хотите обновлять базу данных с помощью свойства, которое на самом деле не изменилось. ReportPropertyChang * также завершится ошибкой для вычисленных полей, для которых нет сопоставлений в базе данных. EDIT1: выяснилось, что необходимо вызвать ReportPropertyChanging перед ReportPropertyChanged.

person Andikki    schedule 21.03.2011
comment
Спасибо, но ReportPropertyChanged недоступен в моем проекте. Это часть Entity Framework ?? - person Laurence; 22.03.2011
comment
Да, это защищенный метод EntityObject. Я сначала не понял, что твой квест был про Silverlight. Я работаю с WPF, не знаю, как это соотносится с SL. - person Andikki; 29.03.2011