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


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

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

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

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

События изменения маршрутизируемых свойств

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

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

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

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

События DependencyPropertyChanged

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

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

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

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

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

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

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

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

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

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

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

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

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

См. также