Спасибо Михаилу за помощь. К сожалению, мне нужно, чтобы привязки оставались постоянно синхронизированными, с отложенной проверкой. В противном случае решение Майкла сделало бы эту работу. Итак, я пошел в несколько ином направлении. Вот решение, которое я в конечном итоге реализовал.
Простая демонстрация: Начнем с самого простого случая: мои бизнес-объекты реализуют IDataErrorInfo
; давайте предположим, что я могу изменить, как это реализовано. Я даю каждому бизнес-объекту дополнительное логическое свойство ValidationEnabled
и изменяю реализацию IDataErrorInfo
, чтобы всегда возвращать нулевой результат, если это свойство имеет значение false.
В демонстрации, о которой я упоминал в своем первоначальном посте, используется объект Contact с двумя свойствами; Имя и фамилия. Я добавил свойство ValidationEnabled и изменил реализацию IDataErrorInfo
следующим образом:
#region IDataErrorInfo Members
public string Error
{
get { throw new System.NotImplementedException(); }
}
public string this[string columnName]
{
get
{
// Initialize
string result = null;
// Perform validation only if enabled
if (ValidationEnabled)
{
switch (columnName)
{
// Validate 'First Name'
case "FirstName":
if (string.IsNullOrEmpty(FirstName))
{
result = "First name has to be set";
}
else if(FirstName.Length < 5)
{
result = "First name must be at least five characters";
}
break;
// Validate "Last Name"
case "LastName":
if (string.IsNullOrEmpty(LastName))
{
result = "Last name has to be set";
}
else if (LastName.Length < 5)
{
result = "Last name must be at least five characters";
}
break;
}
}
// Set return value
return result;
}
}
#endregion
В моей версии простой демонстрации я подключаю кнопку «Отправить» к обработчику событий в коде, который включает проверку и обновляет привязки для обоих текстовых полей:
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var contact = (Contact) DataContext;
contact.ValidationEnabled = true;
var binding = FirstNameBox.GetBindingExpression(TextBox.TextProperty);
binding.UpdateSource();
binding = LastNameBox.GetBindingExpression(TextBox.TextProperty);
binding.UpdateSource();
}
Теперь красные контуры не отображаются, пока я не попытаюсь отправить форму.
Реальный мир: В моем производственном приложении я не управляю бизнес-объектами и не могу изменять их, как в своей простой демонстрации. Итак, я создаю простую сквозную оболочку для бизнес-объекта, которая предоставляет свойства для привязки к представлению и связывает эти свойства с соответствующими свойствами обернутого бизнес-объекта. Оболочка реализует IDataErrorInfo и содержит свойство ValidationEnabled
.
Реализация оболочки IDataErrorInfo всегда возвращает ноль, если проверка не включена. Если проверка включена, то оболочка вызывает реализацию IDataErrorInfo для обернутого объекта и возвращает то, что получает оттуда.
Этот подход будет знаком всем, кто использует шаблон Model-View-ViewModel. То, что мы делаем, - это создание оболочки бизнес-объекта для модели представления, что многими разработчиками считается лучшей практикой MVVM. Он отделяет задачу UI (подавляя красные границы до отправки страницы) от задачи бизнес-модели (простая проверка объектов).
Кроме того, мое производственное приложение не будет использовать обработчики событий в программном коде. Для MVVM кнопка будет подключена к ICommand, который будет содержать логику из обработчика OnButtonClick () в простой демонстрационной версии.
Надеюсь, это пригодится всем, кто исследует эту проблему в будущем.