The team blog of the Expression Blend and Design
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.
( 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.
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:
A simple trigger would look as follows:
Finally, here is a simple action:
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.
It’s been a week since MIX09 started, and since then, many of us Blenders have been busy writing blog posts describing the various new features from Expression Blend 3 in greater detail. This post will point you to those posts:
Blend 3 Overview:
Blend 3 Features:
If you have written any cool blog posts relating to Blend 3, please comment below and I will have another round-up in the near future…hopefully including a link to your post as well.
Cheers! Kirupa :)
The following post is written by Jeff Kelly, one of the developers who worked extensively on both the behaviors runtime as well as the UI inside Blend that makes behaviors easier to use! In this post, he will provide an overview of the three components that make up what we collectively call “Behaviors” in the Expression Blend 3 Preview - Kirupa
One of the major goals of Blend 3 is to make it easier to build interactivity into your applications. In Blend 3, we’ve introduced several new concepts that make writing and reusing interactivity easier than ever before. By writing triggers, actions and behaviors, developers can provide functionality that is cleanly encapsulated and reusable by both developers and designers. Likewise, designers are empowered to add a new level of interactive functionality to their work without ever having to touch a code file.
Triggers and Actions To anyone familiar with WPF, triggers and actions should sound familiar. Blend 3 introduces a similar model, extends support to Silverlight as well as WPF, and allows you to write your own triggers and actions - opening a whole new world of possibilities for what kinds of functionality you can create and reuse in your own applications. Let’s look at what triggers and actions are at a conceptual level, and then dive a little deeper into the basics of the API.
An action is an object that can be invoked to perform an operation. If you think that sounds pretty vague, you’re right. The scope of an action is not constrained: if you can write the code to do something, you could write an action to do the same thing. That said, actions are best written to perform operations that are largely atomic in nature. That is, actions work best when they don’t rely on external state that needs to be persisted between invocations of the action, and that don’t have any dependencies on other actions existing or running in a particular order relative to their invocation.
Actions aren’t particularly useful on their own: they provide functionality to do something, but no way to activate that functionality. In order to invoke an action, we need a trigger. Triggers are objects that contain one or more actions and invoke those actions in response to some stimulus. One very common trigger is one that fires in response to an event (an EventTrigger). Other examples might include a trigger that fires on a timer, or a trigger that fires when an unhandled exception is thrown.
One important thing to note is that triggers and actions are generally meant to be used together arbitrarily. In other words, you should avoid writing an action that makes assumptions about the type of trigger that invokes it, or a trigger that makes assumptions about the actions that belong to it. If you find yourself needing a tight coupling between a trigger and action, you should instead consider a behavior. Speaking of which….
Behaviors Whereas the concepts of triggers and actions have been previously established in an earlier incarnation in WPF, the concept of a behavior is a new one. At a glance, a behavior looks similar to an action: a self-contained unit of functionality. The main difference is that actions expect to be invoked, and when invoked, they will perform some operation. A behavior does not have the concept of invocation; instead, it acts more as an add-on to an object: optional functionality that can be attached to an object if desired. It may do certain things in response to stimulus from the environment, but there is no guarantee that the user can control what this stimulus is: it is up to the behavior author to determine what can and cannot be customized.
As an example, consider a behavior that allows me to drag the object the behavior is attached to around with the mouse. I need to listen to the mouse down, mouse move, and mouse up events on the attached object. In response to the mouse down, I’ll record the mouse position, hook up the mouse move and mouse up handlers and capture the mouse input. On mouse move, I’ll update the position of the object as well as the mouse position. On mouse up, I’ll release mouse capture and unhook my mouse move and mouse down handlers.
My first inclination might be to try and use EventTriggers for each of these events, and write a StartDragAction, MoveDragAction and StopDragAction to invoke in each case. However, it soon becomes apparent that this scenario is not well-addressed by actions: I need to store state between invocations (previous mouse position and the state of the drag), and the operation isn’t atomic. Instead, I can write a behavior that wraps the exact functionality outlined above into a reusable component.
Conclusion Hopefully this post gives you an overview of what makes up a Behavior – the catch all word we use for behaviors, actions, and triggers. In my next post, I will describe the API a bit more and provide some code snippets on how to write each of the behavior components.
Christian Schormann has written a nice article on SketchFlow, so be sure to check it out at the following link: http://electricbeach.org/?p=145
Hi everyone, To follow up on our announcements made today at MIX 09, we are excited to provide a preview of Expression Blend 3:
Expression Blend 3 Preview includes a lot of cool new features, and if you are attending MIX, the sessions we listed in our earlier post will give you a chance to see some of the new features in action. Once the sessions become available online, we will post them on this blog as well. Besides just the sessions, in the upcoming days, weeks, and months, this blog will also provide a detailed look at the various features Expression Blend 3 Preview contains from the various team members who were involved with their design and development.
Send us your Feedback We would also love to hear from you on what you like about our preview and what you would like to see improved. Feel free to comment on the individual blog posts or post on the Expression Blend Forum!
Cheers! Expression Blend Team
Note: The SketchFlow feature demoed at the keynote is not available in this preview, but we do hope to get that feature into your hands in an upcoming release.
Mix 09 this year is going to be pretty interesting – especially if you are an Expression Blend aficionado. You can see the full session information for all Expression Sessions here: https://content.visitmix.com/2009/sessions/?categories=Expression
The following are just the Expression Blend sessions chosen from the above list:
Besides the speakers listed above, Lutz Roeder and I will be there as well. If you happen to stop by any of the above sessions, feel free to chat with any of us. We enjoy the company!
Cheers, Kirupa :-)
When you preview a Silverlight application in Expression Blend, we run the ASP.NET Web Development server in the background to preview your content in an environment that emulates a real-world web server:
On March 9, a signature update to Windows Defender and Microsoft Forefront Security was released that modified your system’s hosts file to address a vulnerability. One of the side effects of this update was that an entry for localhost may have been removed from your hosts file.
This means that, when you preview your application using the ASP.NET Development Server, your browser will simply show a “Page cannot be displayed” (or equivalent) message.
To fix this problem, open C:\Windows\System32\drivers\etc\hosts in Notepad, and add the following entry:
For example, here is what my hosts file looks like (as Lucas pointed out in the comments, if you are not running Windows 7, the below lines may not be commented out):
A subsequent signature update to both Windows Defender and and Forefront Client Security, released on the same day as the earlier update, should not cause this problem.
The original source for this information comes from the Visual Web Developer Team’s blog post on this topic.
Cheers! Kirupa :)