Behaviors Under the Hood – API Details and Constraining the Type

Jeff Kelly is back with Part II of his behaviors triple-feature. This time, he focuses on more details and provides some examples of a simple behavior, trigger, and action - Kirupa

Behaviors and triggers are set on objects in XAML via an attached property, Interactions.Behaviors or Interactions.Triggers respectively. When created via XAML, the IAttachedObject interface is invoked behind-the-scenes to automatically associate your triggers, actions and behaviors with the objects they are attached to in the XAML. It is also possible to call the IAttachedObject members directly from code, although the XAML syntax for these operations is typically sufficient.

image

( Example XAML snippet of a Trigger and Action )

The heart of the behaviors API is the IAttachedObject interface. This interface provides three things: the ability to attach to a specified object, the ability to detach from any object you may be attached to and a property that provides the object to which the IAttachedObject object is currently attached to.
Triggers, action and behaviors all implement IAttachedObject. Additionally, each exposes two virtual functions: OnAttached and OnDetaching, which are called in response to the object being attached or detached to another object. Derived classes typically override these functions to hook/unhook event handlers, initialize state or release resources, and so forth.

A basic behavior has nothing more than what we’ve already described: an OnAttached and OnDetaching virtual and an AssociatedObject property. Depending on the desired behavior, the author may implement their behavior as a black-box, or they may choose to expose relevant properties to configure the operation of a specific instance of a behavior. One additional bit of functionality that is exposed by behaviors and specially tooled by Blend 3 are ICommand properties of behaviors. ICommand properties exposed on behaviors allow users of the behavior a way to interact with a behavior in configurable ways that will be explored in more detail in a future post.

The base class for creating a trigger is the TriggerBase class. The main addition to the basic API that Triggers introduce is the inherited InvokeActions method. A trigger typically hooks up event handlers or initializes some internal mechanism that will be used to determine when to fire (a timer, gesture engine, etc). Once a trigger has determined it is ready to fire, the author simply calls the inherited InvokeActions method and all Actions associated with that trigger will be invoked. This method accepts a parameter as an argument that will be passed to all Actions: this mechanism can be used to pass data between your triggers and your actions, such as EventArgs, or can be set to null and ignored.

Actions have the same basic API extensions as Triggers and Actions, but also require the author to implement the abstract Invoke method. This method is called when the action is invoked, and the functionality of the action should be implemented there. The base class for creating an action is TriggerAction.

One nice component of the API is the differences between Silverlight and WPF are minimal. A behavior written for one platform will need only changes to platform-specific code used in its implementation to compile against the other platform; the behavioral APIs are the same between platforms.

Type Constraints
When creating a trigger, action or behavior, you need to specify a type constraint. This will control the types that your type may be attached to and is particularly useful if you are assuming the existence of a specific event or property on your AssociatedObject. The type constraint is specified as a generic type argument provided to the base class in your class definition. For instance, if you want to write an action that only applies on types derived from Rectangle, you would define it as:

class MyRectangleAction : TriggerAction<Rectangle>

Note: Your constraint type must derive from DependencyObject. If you don’t have a specific constraint, you should specify DependencyObject in the generic field of your derivative class definition.

image

Some Simple Examples
To wrap up this post, let’s look at some sample behaviors, actions, and triggers. Let’s start with a simple example of a behavior:

image

A simple trigger would look as follows:

image

Finally, here is a simple action:

image

This post was a mix between concepts and details. In a future post, I will dive into even more detail on how to write some of these behaviors.

Thanks,
Jeff

Comments

  • Anonymous
    March 30, 2009
    PingBack from http://blog.a-foton.ru/index.php/2009/03/31/behaviors-under-the-hood-%e2%80%93-api-details-and-constraining-the-type/

  • Anonymous
    March 30, 2009
    From the Expression Blend blog; An Introduction to Behaviors, Triggers, and Actions Behaviors Under the

  • Anonymous
    April 03, 2009
    I dont know if this is the right place to comment this but I installed the expressions trial which included office products which were nessessary for the trial. after uninstalling the expressions products i find my microsoft photo editor no longer runs, it opens but never displays anything just in the task bar that its open. This could be any number of reasons but i belive it to be the uninstalation of the office products from the expression trial. mark

  • Anonymous
    April 30, 2009
    Attachable behaviors, as a generic concept, are very useful. Why are these base-classes burried in Expression DLLs? IAttachedObject, Behavior<T>, Tigger<T> and Action<T> should have been factored into seperate DLLs, usable in standard appliation development.

  • Anonymous
    May 31, 2009
    This is really cool stuff! Finally events can do useful things without code-behind. Does this mean that - if I use Interactivity.TriggerAction in my application - I'll have to buy and install Expression for each of my customers? Is this the reason why System.Windows.TriggerActions aren't inheritable?

  • Anonymous
    June 02, 2009
    HdWagner - not at all :-) All projects that get deployed will include the Microsoft.Expression.Interactivity.dll and optionally Microsoft.Expression.Interactions.dll. All Behaviors functionality is containined within those two assemblies, so any deployed project is pretty self-contained. All your customers need to view this content is either Silverlight 3 or WPF 3.5 SP1. Cheers! Kirupa

  • Anonymous
    August 15, 2009
    How do you apply the behavior to say ... all rectangles ... by using a style?

  • Anonymous
    April 13, 2010
    Hey guys, Based on Kirupa's comment, can I safely assume that my applications with this libraries (Microsoft.Expression.Interactions.dll) can be distributed with our products? I really need to check this to take corrective actions (if any) related to our product since we have been using behaviors and triggers for some time now. Cheers

  • Anonymous
    April 14, 2010
    Rod - yes, the Blend 3 version of behaviors can be shipped :) If you are working on the Blend 4 version of behaviors that target Silverlight 4 and .NET 4, you will need to hold off for a little while longer until we give "go-live" redistributable rights. I will write a small blog post here shortly stating this as well so that it isn't hidden in the comments here. Cheers, Kirupa

  • Anonymous
    April 14, 2010
    Thanks Kirupa. Now curiosity assaults me and I need to ask... Is there any reason to distribute this library as 'Microsoft.Expression.Interactions' instead of an extension library of 'System.Windows.Interactions'? If the library will be 'redistributable', will it be a different installer or SDK for development purpuses instead of having the dll with standard Microsoft Blend installations? Cheers and again, thanks for answering so fast.

  • Anonymous
    April 14, 2010
    Rod - I have pinged a few colleagues who can help answer why we went with the naming scheme that we did. Regarding the installer, yes - there will be SDKs for them. For Blend 3, you have the Expression Blend 3 SDK. For Blend 4, you have two SDKs - Expression Blend SDK for .NET 4 and Expression Blend SDK for Silverlight 4. You can download the Blend 3 SDK independent of Blend from the MS Download Center. For the Blend 4 previews/beta/etc., the SDKs will not be posted individually. When we RTM though, those SDKs will be available for individual download as well. Cheers, Kirupa (MS)

  • Anonymous
    April 15, 2010
    The goal for quite a while has been to move the core behaviors infrastructure into the runtime or SDK. There will be API changes when this happens, but the decision to use the System.Windows.Interactivity name was made to try to make this transition smoother if/when it occurs. Internally we try to go through a more rigorous process when designing the APIs in System.Windows.Interactivity as this is intended to be the 'common core' for behaviors. The functionality in Microsoft.Expression.Interactions is what we consider Blend-specific, though there is functionality in here that would also move into a shared location if S.W.I.dll is moved into a shared location. We currently have no plans to integrate all of the functionality in Microsoft.Expression.Interactions.dll to a shared location. Pete

  • Anonymous
    July 29, 2010
    You might be interested in the technique I published on my blog (www.livingagile.com/.../Attaching-Behaviors-from-the-Expression-Blend-SDK-) for assigning behaviors using styles.