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


События изменения свойств (WPF .NET)

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

Важно!

Документация по рабочему столу для .NET 7 и .NET 6 находится в стадии разработки.

Необходимые компоненты

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

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

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

Некоторые события используют тип данных события и делегат, связанные с событиями изменения свойства. Например, события RoutedPropertyChanged и DependencyPropertyChanged имеют определенные сигнатуры. Эти типы событий рассматриваются в следующих разделах.

События RoutedPropertyChanged

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

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

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

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

События DependencyPropertyChanged

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

Одним из примеров события DependencyPropertyChanged является IsMouseCapturedChanged. События DependencyPropertyChanged более распространены, чем события RoutedPropertyChanged.

Аналогично данным события RoutedPropertyChanged, данные событий DependencyPropertyChanged содержат свойства OldValue и NewValue. Из соображений, упомянутых ранее, не используйте обработчик событий изменения свойства, чтобы снова изменить значение свойства.

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

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

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

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

Ограничения триггера свойств

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

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

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

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

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

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

См. также