Blend 3 introduced the idea of Triggers, Actions and Behaviors as a way in which a developer can package up functionality for re-use by a designer in a drag-drop manner.
The way I think of them in my head;
- Action – piece of code that does some single thing.
- Trigger – piece of code that causes some Actions to run at “some point”.
- Behavior – piece of code that attaches itself to some other object and does something with it. Anything.
One of the things that my slightly-too-detailed-obsessed brain struggles to deal with is that in Blend both Behaviors and Actions show up in the Assets panel under a title of Behaviors;
For a developer, this is very upsetting because some of those things are clearly Actions and not Behaviors so it takes a week or two of gnashing of teeth before you begin to accept that this doesn’t really matter and you can get over it and just start to use them
If I’m trying to do something simple such as have the Button in the UI below;
hide the MediaElement above it then I might take a ChangePropertyAction and drag it to my Button. Over in the Objects and Timeline panel I can now see;
and the Properties panel shows me the properties for that particular action. Now, one part of this is about the Trigger which will fire the Action;
Because I dragged this particular Action to the Button Blend has been smart enough to identify the source of the trigger as the Button but I could manually set that via SourceObject/SourceName and I can make that easier by dragging the little target that I’ve circled on the right to an object on the artboard and Blend would then select that as the source of the trigger.
Blend also realised that I would be needing an EventTrigger and it set the EventName on that particular Trigger to “Click”. Note that other types of Trigger would not necessarily have an EventName property.
Another part of these properties relate to the Action itself;
and so I can specify which object the Action is meant to apply itself to via TargetObject/TargetName and ( most importantly ) I get to set which property ( via PropertyName ) the Action is going to apply to. Note that other types of Action would not necessarily have a PropertyName property.
If I drag the little target marker ( circled ) to the MediaElement on my artboard then the properties panel updates;
and if I select a PropertyName then Blend also gives me the opportunity to set the Value;
and my app now “runs” and “works” in the sense that clicking the button hides the video ( note – it’s more likely that you’d do this with states but that’s a different story ).
The other set of properties that I missed out is the Conditions set. If I changed my UI to have a CheckBox;
then I only want to allow my Hide Button to do something if the CheckBox is checked so I can use conditions;
and I can use the “Advanced Options” button highlighted with the arrow above to use “Element Property Binding” to bind this to the IsChecked property on my CheckBox;
and now my Button only hides my MediaElement when my CheckBox is checked.
Naturally, this is just a very simple example.
As an example of using a different kind of trigger, what if I wanted to have my video spin around every 10 seconds ( no, I can’t think of a good reason why I’d want to do that but it’s a different Trigger/Action combination that’s easy to set up ).
If I remove my CheckBox and Button and add this simple animation that spins the video around;
I want to use a ControlStoryboardAction but it’s a lot less obvious where I’d drag it to in the UI. Given the way that I’m going to use it, I don’t think it matters so I just drag it to my LayoutRoot;
and then I can set its properties. Now, I don’t want the EventTrigger that Blend has given me;
so I can use the New button ( arrow’d ) to raise a dialog;
which lets me select ( in this case ) a TimerTrigger. With that in place, I can go and set up my properties;
and now my video spins around every 10 seconds.
The other week, Mike was asking me whether there’s some drag-drop way for controlling a Video from buttons in Silverlight and I couldn’t think of one and I couldn’t think of how to do it using the regular Triggers/Actions that ship with Blend (it’s worth saying that there’s a lot more in the gallery on the web).
So, I thought “no problem” – you just write one and there’s so little code to creating an Action that it’s easy just to at least sketch it out in Blend.
If I want to write an Action that has an effect on a MediaElement then I can use the Projects panel to Add New Item and there’s an Action template on the dialog;
and I could write a little code;
public enum MediaOperation { StartMedia, PauseMedia, StopMedia } public class ControlMediaElementAction : TargetedTriggerAction<MediaElement> { public MediaOperation Operation { get; set; } public ControlMediaElementAction() { this.Operation = MediaOperation.StartMedia; } protected override void Invoke(object o) { if (this.Target != null) { switch (this.Operation) { case MediaOperation.StartMedia: this.Target.Play(); break; case MediaOperation.PauseMedia: this.Target.Pause(); break; case MediaOperation.StopMedia: this.Target.Stop(); break; default: break; } } } }
and I might now add some buttons out onto my UI;
and then associate them with instances of my new ControlMediaElementAction;
and then make sure that the properties of the action are set correctly in each case;
and then that gives me a “working UI”.
Note – there’s many more ways of achieving this kind of thing and it’s likely that I’d want to enable/disable the 3 buttons based on the current state of the MediaElement and that would probably lead me into using commands but, as I said, this is just a very simple example of how easy it might be to build an action ( as an aside, if I was using commands then Blend would still help me here as it has behaviors for invoking commands ).
Speaking of Behaviors – these are different from Actions/Triggers in that they usually represent attached functionality that can’t be represented by Triggers and Actions. This is pretty much the “get out of jail free” card and one simple example is the MouseDragElementBehavior which I can just drop onto my Rectangle here;
and there’s no notion of a Trigger any more just whatever properties the Behavior happens to surface ( in this case that’s ConstrainToParentBounds and X, Y ) but that then enables me to drag the Rectangle around at run time naturally.
All in all – getting that mental picture in your head of what Actions, Triggers, Behaviors do for you and how to set them up in Blend is key as is knowing when you need to go out and look for custom Behaviors or perhaps write your own.