- •А.А. Волосевич
- •1. Общее описание wpf
- •2. ПРостейшее Приложение wpf
- •4. Базовые концепции wpf Иерархия классов
- •Свойства зависимостей и присоединённые свойства
- •Маршрутизируемые события
- •Многопоточность в wpf
- •5. СтруктуРа Оконного приложения wpf
- •Класс Window
- •Класс Application
- •6. Компоновка
- •Размер и выравнивание
- •Основные контейнеры компоновки
- •Прокрутка и декорирование содержимого
- •7. Обзор элеменТов управления
- •Цвета и окантовка:
- •Шрифт содержимого:
- •Элементы управления содержимым
- •Списковые элементы управления
- •Прочие элементы управления
- •8. Фигуры
- •9. Цвет, кисти, прозрачность Представление цвета в wpf
- •Лучшие кисти
- •Прозрачность
- •10. Трансформации и эффекты
- •11. Классы drawing и visual
- •12. Ресурсы
- •Двоичные ресурсы
- •Логические ресурсы
- •13. Привязка данных Базовые концепции привязки данных
- •Практическое использование привязки данных
- •Конвертеры значений
- •Проверка данных
- •14. Стили и триггеры
- •15. ПрИвязка к коллекциям и шаблоны данных
- •16. Представления Данных
- •17. ШАблоны элементов управления
Проверка данных
Для привязки данных, которая передаёт информацию в объект-источник (режимы TwoWay и OneWayToSource), можно реализовать проверку данных. Если данные не проходят проверку, то источник не обновляется, а пользователь получает визуальный сигнал об ошибке.
Первый способ организации проверки заключается в создании и применении проверочных правил. Каждое проверочное правило – это наследник класса ValidationRule с переопределённым методом Validate(). Этот метод получает проверяемое значение и информацию о культуре, а возвращает объект ValidationResult с результатом проверки. Ниже приведён пример правила, ограничивающего десятичные значения некоторым диапазоном:
public class PositivePriceRule : ValidationRule
{
private decimal min = 0;
private decimal max = Decimal.MaxValue;
public decimal Min
{
get { return min; }
set { min = value; }
}
public decimal Max
{
get { return max; }
set { max = value; }
}
public override ValidationResult Validate(object value,
CultureInfo culture)
{
decimal price = 0;
try
{
price = Decimal.Parse((string)value, NumberStyles.Any,
culture);
}
catch
{
return new ValidationResult(false, "Недопустимые символы");
}
if ((price < Min) || (price > Max))
return new ValidationResult(false, "Вне диапазона");
else
return new ValidationResult(true, null);
}
}
Проверочные правила помещают в коллекцию ValidationRules, имеющуюся у каждой привязки:
<TextBox>
<TextBox.Text>
<Binding Path="UnitCost" Mode="TwoWay">
<Binding.ValidationRules>
<local:PositivePriceRule Max="999.99"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Второй способ организации проверки основан на генерировании исключительной ситуации в методе установки свойства объекта-источника:
// фрагмент класса: определение свойства UnitCost
public decimal UnitCost
{
get { return unitCost; }
set
{
if (value < 0)
{
throw new ArgumentException("UnitCost < 0");
}
else
{
unitCost = value;
}
}
}
Исключительные ситуации, возникающие при передаче информации в объект, отлавливаются при помощи специального встроенного проверочного правила ExceptionValidationRule, помещённого в ValidationRules.
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
В качестве альтернативы использованию ExceptionValidationRule можно просто установить свойство привязки ValidatesOnExceptions в значение true.
Третий способ организации проверки данных основан на реализации объектом-источником интерфейса System.ComponentModel.IDataErrorInfo. Интерфейс IDataErrorInfo содержит два элемента: строковое свойство Error и строковый индексатор с ключом-строкой. Свойство Error – это общее описание ошибок объекта. Индексатор принимает имя свойства и возвращает соответствующую детальную информацию об ошибке. Ключевая идея в том, что вся логика обработки ошибок централизована в индексаторе.
Ниже приведён фрагмент класса, реализующего IDataErrorInfo. В примере проверяется на наличие ошибок только одно свойство.
public class Product : IDataErrorInfo
{
public string ModelNumber { get; set; }
// обработка ошибок происходит здесь
public string this[string propertyName]
{
get
{
if (propertyName == "ModelNumber" &&
ModelNumber.Any(c => !Char.IsLetterOrDigit(c)))
return "В ModelNumber допустимы буквы и цифры";
return null;
}
}
// WPF не использует это свойство
public string Error
{
get { return null; }
}
}
Чтобы заставить WPF использовать интерфейс IDataErrorInfo и применять его для проверки ошибок при модификации свойства, нужно добавить встроенное правило DataErrorValidationRule в коллекцию ValidationRules:
<Binding.ValidationRules>
<DataErrorValidationRule />
</Binding.ValidationRules>
В качестве альтернативы использованию DataErrorValidationRule можно установить свойство привязки ValidatesOnDataErrors в значение true.
При нарушении любого из проверочных правил, инфраструктура WPF выполняет следующие шаги:
-
В целевом элементе присоединённое свойство Validation.HasError устанавливается в true.
-
Создаётся объект ValidationError с информацией об ошибке и добавляется в присоединённую коллекцию Validation.Errors.
-
Если свойство привязки NotifyOnValidationError установлено в true, WPF инициирует в целевом элементе присоединённое событие Validation.Error.
Визуальное представление целевого элемента управления также изменяется при возникновении ошибки. Шаблон элемента заменяется шаблоном, определённым в свойстве Validation.ErrorTemplate. Например, в текстовом поле новый шаблон окрашивает контур рамки в красный цвет.