Что касается моего вопроса, могу ли я настроить привязку так, чтобы WPF автоматически проверял свойство Error
интерфейса IDataErrorInfo
, я нашел следующий отрицательный ответ здесь :
Вопрос откто-то:
По сути, я хотел бы знать о свойстве Binding, которое будет запускать тестирование IDataErrorInfo.Error, так как ValidatesOnDataErrors вызывает тестирование IDataErrorInfo.Item.
Ответ службы поддержки Microsoft Online Community:
Установка свойства ValidatesOnDataErrors класса Binding только для тестов IDataErrorInfo.Item, но не для IDataErrorInfo.Error.
Класс Binding не предоставляет свойство для проверки IDataErrorInfo.Error в качестве свойства ValidatesOnDataErrors для проверки IDataErrorInfo.Item на данный момент.
Чтобы получить то, что вам нужно, мы должны установить привязку данных кIDataError.Error ...
Итак, свойство Error
не имеет большего значения, чем определение моегоСобственное ручное свойство (например, CrossPropertyErrors
) в доменных сущностях.WPF не поддерживает тестирование свойства Error
простым встроенным способом.
Редактировать: приведенные выше цитаты относятся к марту 2008 года, поэтому, скорее всего, они связаны с .NET 3.5.Но я не смог найти никаких признаков того, что это изменилось в .NET 4.0.
Редактировать : В конце концов мне пришлось создать собственное рукописное связывание со свойством Error
и заполнитьэто с соответствующими сообщениями об ошибках перекрестного свойства.Каждое изменение любого другого свойства в классе теперь вызывает событие PropertyChanged
как самого измененного свойства, так и свойства Error
, чтобы обновить сообщение об ошибке в пользовательском интерфейсе.
Редактировать 2
Это выглядит примерно так:
Классы модели (или ViewModel):
public class SomeModel : NotificationObject, IDataErrorInfo
{
private string _someProperty;
public string SomeProperty
{
get { return _someProperty; }
set
{
if (_someProperty != value)
{
_someProperty = value;
RaisePropertyChanged("SomeProperty", "Error");
// That's the key: For every changed property a change
// notification also for the Error property is raised
}
}
}
// The above repeats for every property of the model
#region IDataErrorInfo Member
public string Error
{
get
{
var sb = new StringBuilder();
// for example...
if (InvoiceDate < ShippingDate)
sb.AppendLine("InvoiceDate must not be before ShippingDate.");
// more cross-property validations... We have only one Error
// string, therefore we append the messages with
// sb.AppendLine("Another message...") ... etc.
// could all be moved into a separate validation class
// to keep the model class cleaner
return sb.ToString();
}
}
public string this[string columnName]
{
get
{
switch (columnName)
{
case "ShippingDate":
// property-level validations
case "InvoiceDate":
// property-level validations
// etc.
}
return null;
}
}
#endregion
}
NotificationObject
реализует RaisePropertyChanged
:
public abstract class NotificationObject : INotifyPropertyChanged
{
#region INotifyPropertyChanged Member
public event PropertyChangedEventHandler PropertyChanged;
#endregion
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
protected void RaisePropertyChanged(params string[] propertyNames)
{
if (propertyNames == null)
throw new ArgumentNullException("propertyNames");
foreach (var name in propertyNames)
RaisePropertyChanged(name);
}
// ...
}
Тогда в представлении свойство Error
связано, например, с TextBlock
, которое отображает ошибки проверки перекрестного свойства:
<TextBlock Text="{Binding SomeModel.Error}" TextWrapping="Wrap" ... />
Итак: каждое измененное свойство в модели будетуведомить механизм привязки WPF о (потенциальном) изменении свойства Error
, в результате чего будет обновлен текст проверки перекрестного свойства.