I've always been a fan of Commands way back when they were called Actions in the old Delphi days. With .NET, WPF, and Silverlight we have so many new tools available to us. One I’ve been having fun with is behaviors. If you're unfamiliar with these little jewels then check them out here and here. I almost immediately recognized a way to combine my old love of commands with my new love of behaviors. Let’s say we want to attach a generic command to refresh our server to any UI element using a behavior. To start with I came up with a base class to contain my command with a virtual DoCommand() that will be implemented in a descended class but that will take care of the base behavior hookups.
namespace Falafel.Behaviors { public class BaseCommandBehavior : Behavior<DependencyObject> { public BaseCommandBehavior() { IsEnabled = true; } bool _IsEnabled; public bool IsEnabled { get { return _IsEnabled; } set { _IsEnabled = value; if (_IsEnabled) { if (this.Command == null) this.Command = new ActionCommand(this.DoCommand); } else this.Command = null; } } public ICommand Command { get; private set; } public virtual void DoCommand() { } } }
This class gives us the framework for an ICommand and an IsEnabled property for the ICommand. To use this class we only need to override the DoCommand() in a new class. Let’s say our new behavior will refresh a server that we are dealing with.
namespace Falafel.Behaviors { public class RefreshServerBehavior : BaseCommandBehavior { public override void DoCommand() { base.DoCommand(); ServerProxy.Proxy.Refresh(); } } }
<Rectangle x:Name="rectangle" Fill="#FF6CFF00" Stroke="Black" Width="164"> <i:Interaction.Behaviors> <FalafelBehaviors:RefreshServerBehavior> <i:Interaction.Triggers> <i:EventTrigger SourceName="rectangle" EventName="MouseLeftButtonDown"> <i:InvokeCommandAction CommandName="Command"/> i:EventTrigger> i:Interaction.Triggers> FalafelBehaviors:RefreshServerBehavior> i:Interaction.Behaviors> Rectangle>
To add another command behavior is very easy. Let’s say we want to add a server reset command behavior. We just need a new class to override our base DoCommand().
namespace Falafel.Behaviors { public class ResetServerBehavior : BaseCommandBehavior { public override void DoCommand() { base.DoCommand(); ServerProxy.Proxy.Reset(); } } }
public static class AttachCommandBehavior<T> where T : BaseCommandBehavior, new() { public static T AttachBehavior(DependencyObject target, string eventTriggerName) { T behavior = new T(); InvokeCommandAction ica = new InvokeCommandAction() { CommandName = "Command" }; System.Windows.Interactivity.EventTrigger etrigger = new System.Windows.Interactivity.EventTrigger(eventTriggerName); etrigger.Actions.Add(ica); System.Windows.Interactivity.Interaction.GetTriggers(behavior).Add(etrigger); System.Windows.Interactivity.Interaction.GetBehaviors(target).Add(behavior); return behavior; } }
If you look at the structure of the XAML used to attach the command behavior, you can follow the C# code here a little easier. Now that we have our static add method, to add any of our command behaviors in code behind is just a one liner.
void MainPage_Loaded(object sender, RoutedEventArgs e) { AttachCommandBehavior<ResetServerBehavior>.AttachBehavior(buttonReset, "Click"); }
Behaviors are a very important part of WPF and Silverlight that can simplify your application design. If you’re not familiar with them yet, you need to be. Comments are always welcome. For those who have a Google Wave account, I’ve added a Google Wave for this blog that you can find with this wave search – “with:public Silverlight Behavior ICommand Falafel”.
Remember Me
a@href@title, i, strike, u
Copyright © 2003-2010 Falafel Software Inc.
The opinions expressed herein are Falafel's employees own personal opinions and do not represent Falafel Software's view in any way in case they go bananas!