Behaviors and Commands
May 17th, 2009 | 11 Comments
In my previous post, I explained the basics of how to write a simple behavior. I concluded by mentioning that a behavior can actually be made to work with triggers. This is possible despite a Behavior having no real mechanism for a trigger to bury itself into. How is that possible? This post will explain how.
I may have lied a little bit. My previous explanations of Behaviors being solo-artists is not entirely accurate. While Behaviors can work independently without any external influence, unlike an Action, they can also be made to do certain things when certain conditions are met:

That is why the condition part of the original sentence is grayed out as opposed to completely .being removed.
Your Wish is My ICommand
If you want your behavior to be capable of being triggered, you can expose Commands (anything of type ICommand) to be the function that will get called. If you are confused about what I just wrote, don’t worry. Let’s write a behavior that demonstrates this. First, make sure your project has a reference to both the Microsoft.Expression.Interactions and Microsoft.Expression.Interactivity DLLs.
After you have done that, create a new Class file, and before you do anything else, add the following using statement:
- using Microsoft.Expression.Interactivity.Input;
Once you have done this, add the code to turn your class into a behavior:
- public class BehaviorWithCommand : Behavior<DependencyObject>
- {
- public BehaviorWithCommand()
- {
- this.MyCommand = new ActionCommand(this.MyFunction);
- }
- protected override void OnAttached()
- {
- base.OnAttached();
- }
- protected override void OnDetaching()
- {
- base.OnDetaching();
- }
- public ICommand MyCommand
- {
- get;
- private set;
- }
- private void MyFunction()
- {
- MessageBox.Show("Hello World");
- }
- }
Note that I call my behavior BehaviorWithCommand, so be sure to rename your class name and constructor appropriately instead of using my name if you copy/paste. Save and build your project to make sure everything works and nothing is complaining.
Looking at the Blend 3 UI
Go ahead and apply this Behavior any element in your Silverlight or WPF application. Once you have added it to something, select this behavior and look at what is displayed in your Properties Inspector:
Notice that you now see a category called MyCommand, the name of your ICommand property specified in code.
From this category, on the top-right corner, you can use the plus button to add the triggers that will invoke your MyCommand command:
This UI may be new to you if you’ve never played with Behaviors that expose Commands. With commands, notice that I am not stuck with just one Trigger. I am able to add multiple triggers that can each call the same MyCommand function, and just like with Actions, I have the ability to modify the properties of my trigger as well!
How this Works Behind the Scenes
What you see in the Blend UI is a major abstraction of what goes on behind the scenes. To help you understand what is happening better, the following diagram gives you an overview of how commands and Behaviors work together to give you Action-like abilities:
Notice that your behavior exposes a command, and there exists an Action called InvokeCommandAction that does nothing but, as it name implies, invoke commands. Since this is an Action, you have the abilities to set triggers on it. All you ever see in the Blend UI is the Command and the Triggers that you want to set on it. Behind the scenes, we map your trigger to the InvokeCommandAction that is associated with the Command.
This means the trigger has no knowledge of the behavior. They are completely decoupled and fit with the self-contained, solo model that I have been describing about Behaviors for the past few posts. Because they interact with Actions that, in turn, interact with Commands exposed by the Behavior, you have the ability to have our behavior do things with some external input just like you can with Actions.
Conclusion
All right. This wraps up my current series of posts describing Behaviors themselves. You may find yourself wondering why you would ever want to use a Behavior when Actions just seem much easier to use and conceptually understand. The answer is, for the most part, rarely.
Unless you want the ability that Behaviors have where you can internally manage state independent of being tied to a trigger, you will find a Trigger and Action pair to be your best friends as you navigate through this sea of interactivity. For a class of interactions, especially those involving state, having a Behavior handy does not hurt either though.
Cheers!
Kirupa





May 17th, 2009 at 5:57 pm
Thanks for an excellent post kirpua, a lot of the blend designer and behavior functionality is certainly not very discoverable at the moment.
One thing I’d love to see changed before release is that Behaviors, Triggers and Actions inherit from FrameworkElement rather than DependencyObject, and therefore able to be the target for {Binding} expressions.
An excellent example is that I’d like to be able to bind an ICommand exposed by my ViewModel (usng the MVVM pattern) to a behavior. Without binding the code becomes a lot more complicated.
This is my top wishlist item to be changed in the beta, as the possiblities (especially with ElementName bindings) become a lot richer.
Thanks
May 17th, 2009 at 7:30 pm
Hi Nigel,
That is my number one request as well, but it is something that we will not be changing with our Behaviors in the Silverlight 3 timeframe unfortunately.
As you noted, Behaviors inherit from DependencyObject in both WPF and Silverlight. WPF does support binding to DependencyObjects, and therefore, you do get binding support in the Behaviors you use in WPF projects.
In Silverlight 3, because of the lack of data bindability with DependencyObjects, Behaviors do not get this functionality as well.
From an architectural point of view, having Behaviors be DependencyObjects is better than them being FrameworkElements. While that is really unfortunate in the short run, hopefully this design in the long run will be better once/if Silverlight begins to support binding on non-FrameworkElements.
In the interim, Pete Blois has blogged about a workaround for this: http://blois.us/blog/2009/04/datatrigger-bindings-on-non.html
Thanks for the post, and do let me know if there are any other things you would like to see with Behaviors or Blend in general =)
Cheers!
Kirupa
May 17th, 2009 at 7:44 pm
Thanks, I’ve see that post from Pete and got the functionality that I’m after going, just a lot of wiring for simple behaviors and makes them very hard to unit test effectively
May 17th, 2009 at 8:17 pm
Would you mind posting the generated XAML?
May 17th, 2009 at 9:15 pm
Michael, I am unable to paste the XAML in the comments. If you can send me an e-mail kirupac[at]microsoft.com, I can e-mail you the XAML generated.
May 19th, 2009 at 10:50 am
[...] >Behaviors and Commands [...]
May 24th, 2009 at 4:06 am
cool stuff
but does this work in silverlight as well? i didnt think silverlight had ICommand?
May 24th, 2009 at 2:16 pm
aL – my above example is a Silverlight example actually
Silverlight does have a version of ICommand: http://msdn.microsoft.com/en-us/library/system.windows.input.icommand(VS.95).aspx
While this functionality may not be entirely on par with that of WPF, for what we are using ICommands for in Behaviors, it seems to do the job well.
June 25th, 2009 at 2:36 pm
[...] too many articles talking about attached behavior and commands. The best I found so far is from kirupa.com. He has a lot of good articles describing the details of behavior and command. Therefore, I am not [...]
June 25th, 2009 at 2:49 pm
Hi, I have created a sample for Behavior and Command.
http://www.shinedraw.com/designer-extensibility/silverlight-attached-behavior-and-command/
Please take a look if you are interested.
October 5th, 2009 at 1:46 pm
vrbihtqmayok