Using triggers to define the behavior of a WPF control
During an application's lifetime, objects in the user interface undergo changes to their state. State is often expressed in terms oriented toward the user—for example, a button's mouse-over state, or a menu item's pressed state. These two example states are implemented on objects by using the UIElement.IsMouseOver property and the MenuItem.IsPressed property, respectively.
But the value of these properties, and therefore the states they represent, are not in themselves visible to the user. IsMouseOver and IsPressed are not visual properties. To be observed, a change in a nonvisual property must trigger a change in a visual property (such as Background or Opacity). For example, a button in the mouse-over state appears curved where it was flat before, or the background color of a menu item changes when it is pressed.
In addition to changing their state, objects also raise events. For example, a button raises the MouseEnter and MouseLeave events as the pointer crosses its bounds. An event, too, has no appearance of its own and it must therefore trigger a change in a visual property to be noticed by the user.
Triggers (and animation timelines) can be created in the root of a document or in a style that is applied to a control. For example, you can modify the style of a button to create subtle changes in the button's appearance when the pressed and rollover states of the button change. Any button to which the style is applied would behave the same way. For an example, see Try it: Add animation to a button.
There are two types of triggers:
Property trigger The mechanism by which a change in one property triggers either an instant or an animated change in another property.
Event trigger The mechanism by which an event triggers an animated change in a property.
The following image shows the Triggers user interface, with two property triggers (IsMouseOver and IsPressed), and an event trigger (target-element.Loaded). The IsMouseOver property trigger is selected, showing the property that is changed (Border.Background), and the timeline that is triggered (OnLoaded1).
A property trigger defines a trigger condition together with what actions should follow from the condition being satisfied. An example condition is "the IsMouseOver property of button1 is true." Example actions are "set the Foreground property of button1 to Red and begin the animation named Expand, which scales the button up."
Setting Foreground to Red is an example of a kind of action named a property setter. The setter is in effect only as long as the condition is met; the property reverts to its former value when the condition is no longer met. Beginning the animation named Expand is an example of an enter action; the action happens when the condition becomes met. An exit action happens when the condition is no longer met. Only animations can be controlled from enter or exit actions. The following figure shows the life cycle for this example property trigger.
Notice that the setter suffices to control the Foreground property throughout the life cycle. By stage 5, the Foreground is automatically set back to Black once again. However, any property animations performed by the enter action are not undone. By stage 5, the button is still scaled to a larger size. The solution is to design a Contract animation that scales the button down again, and then begin this new animation in an exit action.
A property trigger can be defined only in a style or in a template, although generally the best practice with triggers is to put them in a template when you can.
An event trigger defines a trigger condition together with what actions should follow from the condition being satisfied. An example condition is "the MouseEnter event is raised on button1." Example actions are "begin the animation named Expand, which scales the button up."
The example action is the same as the enter action used earlier in the property trigger example. An event trigger does not have the same life cycle as a property trigger. Instead, it just runs actions in response to an event. So, an event trigger does not have enter and exit actions, just actions.
If we want a button to scale up when the pointer enters its bounds and then return to regular size when the pointer leaves its bounds, we have to define a pair of event triggers with complementary scaling animations. An event trigger can be defined in a style or in a template or in the LayoutRoot.
Property trigger or event trigger?
Often, a property is mirrored by a corresponding set of events and you can decide whether to design a property trigger or two event triggers. For example you can achieve the same effect with an IsMouseOver property trigger or a pair of MouseEnter and MouseLeave event triggers. Use property triggers when you can, and event triggers when you have to—for example when you're not inside a style or template. When you do have to use event triggers, to compensate for the lack of setters, you can create a pair of animations with keyframes at time zero.
Trigger or event handler method?
You can use event handlers to do anything that a trigger can do, and you can add any other programming logic, such as setting a property on another element, loading a new document, creating a new element, and so on. This is because event handler methods are defined in the code-behind file of your document, in C# or Microsoft Visual Basic .NET. For more information, see Writing code that will respond to events.
For a list of events that you can hook up to, either by using triggers or by using event handler methods, see Controls, properties, and events reference.