Сводка по главе 23. Триггеры и реакции на событие
Примечание.
Эта книга была опубликована весной 2016 года и с тех пор не обновлялась. Многое в этой книге остается ценным, но некоторые материалы устарели, а некоторые разделы перестали быть полностью верными или полными.
Триггеры и реакции на событие похожи тем, что используются в файлах XAML для упрощения взаимодействий элементов за пределами использования привязок данных и расширения функциональных возможностей элементов XAML. Как триггеры, так и реакции на событие почти всегда сочетаются с визуальными объектами пользовательского интерфейса.
Для использования триггеров и реакций на событие VisualElement
и Style
поддерживают два свойства коллекции:
VisualElement.Triggers
иStyle.Triggers
с типомIList<TriggerBase>
;VisualElement.Behaviors
иStyle.Behaviors
с типомIList<Behavior>
;
Триггеры
Триггером называется условие (изменение свойства или срабатывание события), которое приводит к некоторому отклику (изменение другого свойства или выполнение некоторого кода). Свойство Triggers
для VisualElement
и Style
имеет тип IList<TriggersBase>
. TriggerBase
является абстрактным классом, от которого наследуются четыре запечатанных класса:
Trigger
для ответов на основе изменений свойств;EventTrigger
для ответов на основе выполнения событий;DataTrigger
для ответов на основе привязки данных;MultiTrigger
для ответов на основе нескольких триггеров.
Триггер всегда задается для элемента, свойство которого изменяется этим триггером.
Простейший триггер
Класс Trigger
проверяет изменение значения свойства и отвечает, устанавливая другое свойство того же элемента.
Trigger
определяет три свойства:
Property
типаBindableProperty
Value
типаObject
Setters
с типомIList<SetterBase>
— это свойство содержимогоTrigger
.
Кроме того, Trigger
требует установить следующее свойство, наследуемое от TriggerBase
:
TargetType
, чтобы указывать тип элемента, к которому присоединенTrigger
Здесь Property
и Value
составляют условие, а коллекция Setters
определяет ответ. Если Property
имеет значение, указанное в Value
, применяются объекты Setter
из коллекции Setters
. Если Property
имеет другое значение, методы задания удаляются. Setter
определяет два свойства, которые совпадают с двумя первыми свойствами Trigger
:
В примере EntryPop показано, как применение Trigger
к Entry
позволяет увеличивать размер Entry
с помощью свойства Scale
, когда свойство IsFocused
объекта Entry
имеет значение true
.
Обычно так не делают, но Trigger
можно задавать в коде, как показано в примере EntryPopCode.
Пример StyledTriggers демонстрирует, как задать Trigger
из Style
для применения к нескольким элементам Entry
.
Действия триггера и анимации
Вы также можете выполнять при активации триггера небольшой фрагмент кода. Этот код может быть анимацией, которая использует определенное свойство. Один из распространенных приемов — использовать EventTrigger
с определением двух свойств:
Event
с типомstring
, где содержится имя события;Actions
с типомIList<TriggerAction>
, где определен список выполняемых в ответ действий.
Чтобы использовать его, нужно написать производный от TriggerAction<T>
класс, обычно это TriggerAction<VisualElement>
. Определите свойства в этом классе. Это простые свойства CLR, а не привязываемые свойства, так как TriggerAction
не наследует от BindableObject
. Необходимо переопределить метод Invoke
, который вызывается при активации действия. В качестве аргумента он принимает целевой элемент.
В качестве примера ScaleAction
используется класс в библиотеке Xamarin.FormsBook.Toolkit. Он вызывает свойство ScaleTo
для анимации свойства Scale
указанного элемента. Так как одно из его свойств имеет тип Easing
, класс EasingConverter
позволяет использовать в XAML стандартные статические поля Easing
.
В примере EntrySwell показано, как вызывать ScaleAction
из EventTrigger
объектов, отслеживающих события Focused
и Unfocused
.
В примере CustomEasingSwell показано, как определить пользовательскую функцию для реалистичной анимации для ScaleAction
в файле кода программной части.
Действия также можно вызывать с помощью Trigger
(в отличие от EventTrigger
). Для этого необходимо знать, что TriggerBase
определяет две коллекции:
EnterActions
типаIList<TriggerAction>
ExitActions
типаIList<TriggerAction>
Пример EnterExitSwell демонстрирует способ использования этих коллекций.
Дополнительные триггеры событий
Класс ScaleUpAndDownAction
из библиотеки Xamarin.FormsBook.Toolkit дважды вызывает ScaleTo
для увеличения и уменьшения размера. Пример ButtonGrowth использует этот прием в EventTrigger
с примененным стилем, чтобы обеспечить визуальное подтверждение нажатия Button
. Эта двойная анимация также поддерживается двумя действиями в коллекции типа DelayedScaleAction
.
Класс ShiverAction
из библиотеки Xamarin.FormsBook.Toolkit определяет действие дрожания с возможностью настройки. Эта техника демонстрируется в примере ShiverButtonDemo.
Класс NumericValidationAction
в библиотеке Xamarin.FormsBook.Toolkit действует только для элементов Entry
и присваивает свойству TextColor
значение red, если свойство Text
не является double
. Этот подход демонстрируется в примере TriggerEntryValidation.
Триггеры данных
DataTrigger
похож на Trigger
, за исключением того, что он отслеживает привязку данных, а не ожидает изменений значения свойства. Это позволяет свойству одного элемента влиять на свойство в другом элементе.
DataTrigger
определяет три свойства:
Для примера GenderColors требуется библиотека SchoolOfFineArt. Он задает цвета для имен учащихся: синий или розовый в зависимости от свойства Sex
:
В примере ButtonEnabler для свойства IsEnabled
элемента Entry
устанавливается значение False
, если свойство Length
свойства Text
элемента Entry
равно 0. Обратите внимание, что свойство Text
инициализируется пустой строкой. По умолчанию оно имеет значение null
, при котором DataTrigger
не будет работать правильно.
Объединение условий в MultiTrigger
MultiTrigger
представляет собой коллекцию условий. Когда они все получают значение true
, применяются методы задания. Этот класс определяет два свойства:
Conditions
типаIList<Condition>
Setters
типаIList<Setter>
Condition
является абстрактным классом и имеет два дочерних класса:
PropertyCondition
, который имеет свойстваProperty
иValue
, какTrigger
BindingCondition
, который имеет свойстваBinding
иValue
, какDataTrigger
В примере AndConditions элемент BoxView
выделяется, только если включены все четыре элемента Switch
.
В примере OrConditions показано, как можно изменять цвет BoxView
при включении любого из четырех элементов Switch
. Это требует применения закона де Моргана и обращения всей логики.
Сочетание логики И и ИЛИ реализовать сложнее, и обычно для этого нужны невидимые элементы Switch
для промежуточных результатов. В примере XorConditions показано, как включать Button
, если один и только один из двух элементов Entry
содержит введенный текст.
Поведение
Все, что можно сделать с помощью триггера, можно реализовать и с помощью реакции на событие, но для этого всегда требуется производный от Behavior<T>
класс с переопределением следующих двух методов:
В качестве аргумента принимается элемент, к которому присоединяется реакция на событие. Как правило, метод OnAttachedTo
присоединяет некоторые обработчики событий, а OnDetachingFrom
отсоединяет их. Так как этот класс обычно сохраняет некоторые сведения о состоянии, его нельзя использовать совместно в Style
.
Пример BehaviorEntryValidation аналогичен триггеру TriggerEntryValidation, за исключением того, что он использует поведение — NumericValidationBehavior
класс в Xamarin.Formsбиблиотеке Book.Toolkit.
Реакция на событие с поддержкой свойств
Behavior<T>
наследует от Behavior
, который наследует от BindableObject
, а значит для реакции на событие можно определить привязываемые свойства. Эти свойства можно активно использовать в привязке данных.
Этот подход демонстрируется в программе EmailValidationDemo на основе класса ValidEmailBehavior
из библиотеки Xamarin.FormsBook.Toolkit. ValidEmailBehavior
имеет привязываемое свойство только для чтения и служит источником в привязках данных.
В примере EmailValidationConv эта же реакция на событие используется для отображения индикатора другого типа, который информирует о допустимом формате адреса электронной почты.
Пример EmailValidationTrigger является модификацией предыдущего примера. ButtonGlide использует DataTrigger
в сочетании с той же реакцией на событие.
Переключатели и флажки
Поведение выключателя можно инкапсулировать в классе, например ToggleBehavior
из библиотеки Xamarin.FormsBook.Toolkit, а затем определить все визуальные элементы для переключателя полностью в XAML.
В примере ToggleLabel используется ToggleBehavior
с DataTrigger
, чтобы применить Label
с двумя текстовыми строками для переключения.
Пример FormattedTextToggle расширяет эту схему, переключаясь между двумя объектами FormattedString
.
Класс ToggleBase
в библиотеке Xamarin.FormsBook.Toolkit является производным от ContentView
, определяет свойство IsToggled
и содержит ToggleBehavior
для логики переключения. Это упрощает определение выключателя в XAML, как показано в примере TraditionalCheckBox.
SwitchCloneDemo включает класс, производный SwitchClone
от ToggleBase
класса и использующий TranslateAction
класс для создания кнопки переключения, которая похожа на Xamarin.FormsSwitch
.
Класс RotateAction
в Xamarin.FormsBook.Toolkit предоставляет анимацию, на которой основан анимированный рычаг в примере LeverToggle.
Реагирование на касания
Недостаток EventTrigger
заключается в том, что вы не можете присоединить его к TapGestureRecognizer
, чтобы реагировать на касания. Чтобы обойти эту проблему, в библиотеку Xamarin.FormsBook.Toolkit включен TapBehavior
.
В примере BoxViewTapShiver используется TapBehavior
, чтобы применить описанный выше ShiverAction
для нажатых элементов BoxView
.
В примере ShiverViews показано, как сократить объем разметки с помощью инкапсуляции класса ShiverView
.
Переключатели
Библиотека Xamarin.FormsBook.Toolkit также имеет класс RadioBehavior
для создания переключателей, сгруппированных по имени группы string
.
Программа RadioLabels использует текстовые строки в качестве переключателя. В примере RadioStyle используется Style
, чтобы различать нажатые и не нажатые кнопки. Пример RadioImages использует текстовые строки в качестве переключателей.
В примере TraditionalRadios отображаются переключатели традиционного вида с точкой внутри окружности.
Исчезновение и ориентация
В последнем примере MultiColorSliders вы с помощью переключателей можете выбирать любое из трех разных представлений для выбора цвета. Эти три представления плавно появляются и исчезают с использованием FadeEnableAction
из библиотеки Xamarin.FormsBook.Toolkit.
Эта программа также реагирует на изменения ориентации (книжная или альбомная) с помощью GridOrientationBehavior
из библиотеки Xamarin.FormsBook.Toolkit.