Поделиться через


События изменения свойства

Windows Presentation Foundation (WPF) определяет несколько событий, которые возникают в ответ на изменение значения свойства. Часто этим свойством является свойство зависимостей. Самим событием иногда является перенаправляемое событие, а иногда — стандартное событие CLR. Определение события зависит от сценария, так как некоторые изменения свойств лучше перенаправлять через дерево элементов, тогда как другие в основном влияют только на объект, в котором это свойство изменено.

Определение события изменения свойства

Не все события, сообщающие об изменении свойства, явным образом определяются как событие изменения свойства на основании шаблона сигнатуры или именования. Как правило, в описании события в документации по пакету SDK указывается, связано ли событие непосредственно с изменением значения свойства, и содержатся перекрестные ссылки между свойством и событием.

События RoutedPropertyChanged

Некоторые события используют тип данных события и делегат, которые явно используются для событий изменения свойств. Тип данных события — RoutedPropertyChangedEventArgs<T>, а делегат — RoutedPropertyChangedEventHandler<T>. Данные события и делегат имеют параметр универсального типа, который используется для указания фактического типа изменяющегося свойства при определении обработчика. Данные события содержат два свойства (OldValue и NewValue), которые затем передаются как аргумент типа в данных события.

"Перенаправляемая" часть имени указывает, что событие изменения свойства зарегистрировано как перенаправляемое событие. Преимуществом перенаправления события изменения свойства является то, что верхний уровень элемента управления может получать события изменения свойств, если свойства дочерних элементов (составные части элемента управления) изменяют значения. Например, можно создать элемент управления, который включает элемент управления RangeBase, такой как Slider. Если значение свойства Value изменяется в части ползунка, может потребоваться обработка этого изменения в родительском элементе управления, а не в этой части.

Поскольку имеется старое и новое значение, то может казаться заманчивым использовать этот обработчик событий в качестве проверяющего элемента управления для значения свойства. Однако большинство событий изменения свойств создается не для этого. Как правило, предоставляются значения, на основе которых можно действовать в других логических областях кода, но на самом деле изменение значений из обработчика событий не рекомендуется и может привести к непреднамеренной рекурсии в зависимости от реализации обработчика.

Если свойство является пользовательским свойством зависимостей, или вы работаете с производным классом, в котором определен код создания экземпляра, то существует гораздо лучший механизм отслеживания изменений свойств, который встроен в систему свойств WPF, — обратные вызовы системы свойств CoerceValueCallback и PropertyChangedCallback. Дополнительные сведения об использовании системы свойств WPF для проверки и приведения см. в разделах Проверка и обратные вызовы свойства зависимостей и Пользовательские свойства зависимостей.

События DependencyPropertyChanged

Другая пара типов, которые являются частью сценария события изменения свойств, — это DependencyPropertyChangedEventArgs и DependencyPropertyChangedEventHandler. События для этих изменений свойств не перенаправляются; это стандартные события CLR. DependencyPropertyChangedEventArgs является необычным типом отчетов данных о событиях, потому что он не является производным от EventArgs; DependencyPropertyChangedEventArgs — это структура, а не класс.

События, которые используют DependencyPropertyChangedEventArgs и DependencyPropertyChangedEventHandler, более распространены, чем события RoutedPropertyChanged. Примером события, которое использует эти типы, является IsMouseCapturedChanged.

Как и RoutedPropertyChangedEventArgs<T>, DependencyPropertyChangedEventArgs также сообщает старое и новое значения свойства. Аналогично это относится и к тому, что вы можете делать со значениями. Обычно не рекомендуется пытаться снова изменить значения в отправителе в ответ на это событие.

Триггеры свойств

С событием изменения свойств тесно связана другая концепция — триггер свойств. Триггер свойств создается внутри стиля или шаблона и позволяет создавать условное поведение на основе значения свойства, которому назначается триггер.

У триггера свойств должно быть свойство зависимостей. Оно может быть (и часто является) свойством зависимостей только для чтения. Хорошим указанием на то, что свойство зависимостей, предоставляемое элементом управления, хотя бы частично разработано как триггер свойства, является Is в начале имени свойства. Свойства с таким именованием часто являются логическим свойством зависимостей только для чтения, а основной сценарий для свойства — предоставление состояния элемента управления, которое может иметь последствия для пользовательского интерфейса реального времени и, следовательно, является кандидатом на роль триггера свойств.

Некоторые из этих свойств также имеют специальное событие изменения свойства. Например, свойство IsMouseCaptured имеет событие изменения свойства IsMouseCapturedChanged. Само свойство доступно только для чтения, его значение определяется системой ввода. Система ввода создает IsMouseCapturedChanged при каждом изменении в режиме реального времени.

По сравнению с истинным событием изменения свойства, использование триггера свойств для реагирования на изменение свойства имеет некоторые ограничения.

Триггеры свойств работают через логику точного соответствия. Нужно указать свойство и конкретное значение, для которого будет срабатывать триггер. Например, <Setter Property="IsMouseCaptured" Value="true"> ... </Setter>. Из-за этого ограничения большая часть триггеров свойств будет использоваться для логических свойств или свойств, которые принимают определенное значение перечисления, когда возможный диапазон значений достаточно управляем, чтобы определить триггер для каждого случая. Триггеры свойств могут существовать только для специальных значений, например когда количество элементов достигает нуля, а также нет триггера, который учитывает случаи, когда значение свойства изменяется от нуля (вместо триггеров для всех случаев вам может понадобиться обработчик события кода или поведение по умолчанию, которое снова возвращается из состояния триггера, когда значение отлично от нуля).

Синтаксис триггера свойств аналогичен оператору if в программировании. Если условие триггера истинно, тогда "тело" триггера свойств "выполняется". "Тело" триггера свойств является не кодом, а разметкой. Разметка ограничена использованием одного или нескольких элементов Setter для задания других свойств объекта, для которого применяется стиль или шаблон.

Чтобы сместить условие if триггера свойств, которое имеет широкий выбор возможных значений, обычно рекомендуется установить это же значение свойства в качестве значения по умолчанию с помощью Setter. Таким образом, содержащий Trigger метод задания будет иметь приоритет, когда условие триггера верно, а Setter, который не входит в Trigger, будет иметь приоритет всякий раз, когда условие триггера не выполняется.

Триггеры свойств, как правило, подходят для сценариев, в которых одно или несколько свойств Appearance должны изменяться в зависимости от состояния другого свойства в том же элементе.

Дополнительные сведения о триггерах свойств см. в разделе Использование стилей и шаблонов.

См. также