Summary of Chapter 23. Triggers and behaviors
Triggers and behaviors are similar, in that they are both intended to be used in XAML files to simplify element interactions beyond the use of data bindings, and to extend the functionality of XAML elements. Both triggers and behaviors are almost always used with visual user-interface objects.
To support triggers and behaviors, both
Style support two collection properties:
A trigger is a condition (a property change or the firing of an event) that results in a response (another property change or running some code). The
Triggers property of
Style is of type
TriggerBase is an abstract class from which four sealed classes derive:
Triggerfor responses based on property changes
EventTriggerfor responses based on event firings
DataTriggerfor responses based on data bindings
MultiTriggerfor responses based on multiple triggers
The trigger is always set on the element whose property is being changed by the trigger.
The simplest trigger
Trigger class checks for a change of a property value and responds by setting another property of the same element.
Trigger defines three properties:
IList<SetterBase>, the content property of
Trigger requires that the following property inherited from
TriggerBase be set:
TargetTypeto indicate the type of the element on which the
Value comprise the condition, and the
Setters collection is the response. When the indicated
Property has the value indicated by
Value, then the
Setter objects in the
Setters collection are applied. When the
Property has a different value, the setters are removed.
Setter defines two properties that are the same as the first two properties of
The EntryPop sample demonstrates how a
Trigger applied to an
Entry can increase the size of the
Entry via the
Scale property when the
IsFocused property of the
Although it's not common, the
Trigger can be set in code, as the EntryPopCode sample demonstrates.
The StyledTriggers sample demonstrates how the
Trigger can be set in a
Style to apply to multiple
Trigger actions and animations
It is also possible to run a little code based on a trigger. This code can be an animation that targets a property. One common way is to use an
EventTrigger, which defines two properties:
string, the name of an event
IList<TriggerAction>, a list of actions to run in response.
To use this, you need to write a class that derives from
TriggerAction<VisualElement>. You can define properties in this class. These are plain CLR properties rather than bindable properties because
TriggerAction doesn't derive from
BindableObject. You must override the
Invoke method that is called when the action is invoked. The argument is the target element.
ScaleAction class in the Xamarin.FormsBook.Toolkit library is an example. It calls the
ScaleTo property to animate the
Scale property of an element. Because one of its properties is of type
EasingConverter class lets you use the standard
Easing static fields in XAML.
The EntrySwell sample demonstrates how to invoke the
EventTrigger objects that monitor the
The CustomEasingSwell sample shows how to define a custom easing function for
ScaleAction in a code-behind file.
You can also invoke actions using a
Trigger (as distinguished from
EventTrigger). This requires that you are aware that
TriggerBase defines two collections:
The EnterExitSwell sample demonstrates how to use these collections.
More event triggers
ScaleUpAndDownAction class in the Xamarin.FormsBook.Toolkit library calls
ScaleTo twice to scale up and down. The
ButtonGrowth sample uses this in a styled
EventTrigger to provide visual feedback when a
Button is pressed. This double animation is also possible using two actions in the collection of type
NumericValidationAction class in the Xamarin.FormsBook.Toolkit library is restricted to
Entry elements and sets the
TextColor property to red if the
Text property is not a
TriggerEntryValidation sample demonstrates it.
DataTrigger is similar to the
Trigger except that instead of monitoring a property for value changes, it monitors a data binding. This allows a property in one element to affect a property in another element.
DataTrigger defines three properties:
The ButtonEnabler sample sets the
IsEnabled property of an
False if the
Length property of the
Text property of the
Entry equals 0. Notice that the
Text property is initialized to an empty string; by default it is
null, and the
DataTrigger wouldn't work correctly.
Combining conditions in the MultiTrigger
MultiTrigger is a collection of conditions. When they are all
true, then setters are applied. The class defines two properties:
Condition is an abstract class and has two descendent classes:
PropertyCondition, which has
BindingCondition, which has
In the AndConditions sample, a
BoxView is only colored when four
Switch elements are all turned on.
The OrConditions sample demonstrates how you can make a
BoxView a color when any of four
Switch elements are turned on. This requires an application of De Morgan's Law and reversing all the logic.
Combining AND and OR logic is not so easy and generally requires invisible
Switch elements for intermediate results. The
XorConditions sample demonstrates how a
Button can be enabled if either of two
Entry elements have some text typed in, but not if they both have some text typed in.
Anything you can do with a trigger, you can also do with a behavior, but behaviors always require a class that derives from
Behavior<T> and overrides the following two methods:
The argument is the element that the behavior is attached to. Generally, the
OnAttachedTo method attaches some event handlers, and
OnDetachingFrom detaches them. Because such a class usually saves some state, it generally cannot be shared in a
Behaviors with properties
Behavior<T> derives from
Behavior, which derives from
BindableObject, so bindable properties can be defined on a behavior. These properties can be active in data bindings.
This is demonstrated in the
EmailValidationDemo program that makes use of the
ValidEmailBehavior class in the Xamarin.FormsBook.Toolkit library.
ValidEmailBehavior has a read-only bindable property and serves as a source in data bindings.
The EmailValidationConv sample uses this same behavior to display another type of indicator to signal that an email address is valid.
The EmailValidationTrigger sample is a variation on the previous sample. ButtonGlide uses a
DataTrigger in combination with that behavior.
Toggles and check boxes
It's possible to encapsulate the behavior of a toggle button in a class such as
ToggleBehavior in the Xamarin.FormsBook.Toolkit library, and then define all the visuals for the toggle entirely in XAML.
The ToggleLabel sample uses the
ToggleBehavior with a
DataTrigger to use a
Label with two text strings for the toggle.
The FormattedTextToggle sample extends this concept by switching between two
ToggleBase class in the Xamarin.FormsBook.Toolkit library derives from
ContentView, defines an
IsToggled property, and incorporates a
ToggleBehavior for the toggle logic. This makes it easier to define the toggle button in XAML, as demonstrated by the TraditionalCheckBox sample.
Responding to taps
The BoxViewTapShiver sample uses
TapBehavior to use the earlier
ShiverAction for tapped
The ShiverViews sample shows how to cut down on the markup by encapsulating a
The RadioLabels program uses text strings for its radio button. The RadioStyle sample uses a
Style for the difference in appearance between checked and unchecked buttons. The
RadioImages sample uses boxed images for its radio buttons:
The TraditionalRadios sample draws traditional appearing radio buttons with a dot inside a circle.
Fades and orientation
The final sample, MultiColorSliders allows you to switch between three different color-selection views using radio buttons. The three views fade in and out using a
FadeEnableAction in the Xamarin.FormsBook.Toolkit library.
The program also responds to changes in orientation between portrait and landscape using a
GridOrientationBehavior in the Xamarin.FormsBook.Toolkit library.
We'd love to hear your thoughts. Choose the type you'd like to provide:
Our feedback system is built on GitHub Issues. Read more on our blog.