just want to wish all the best to all my blog readers and the rest of the community. 2008 was a very good year for me and .NET…. a lot of interesting new stuff came out that made 2008 a year to remember. I’m sure next year will be also a good year, I can’t wait.
Thanks for the support everyone gave me in 2008. Hope I can help in 2009 as well
YOUAfter publishing my AttachedCommandBehavior library, (you can read about this here), some WPF Disciples recommended some new features to make the library cover more use cases. Thanks William Kempf your input was amazing!
I added 2 new features
- Support for Collection of binding to commands
- Support for Light weight Commands or as I call them Action
Support for Collection of binding to commands
This is a very handy feature. Let’s say you want to hook a command to the MouseDown but also want to hook up to the MouseEnter event, in ACB v1 you could now do this because you could only Bind one command at a time. Now the ACB v2 is supporting a collection of what I call BehaviorBinding. This is really powerful because it enables you to hook up to N number of events. The code would look something like this
So basically there is a read-only attached property Behaviors (which by the way it is something really cool, have a look at this post to find out more) and here you can define as many BehaviorBindings as you wish. I really love this part because I had to do some WPF tricks like the Freezable trick to make DataBinding work even in the Behaviors collections.
Support for Light weight Commands or as I call them Action
This is something really cool as well. Me and the Disciples were discussing how this could be a way to work around the fact that you cannot have a command handler in the XAML pointing to a method in the ViewModel, then William Kempf said
“Commands imply, to
me at least, CanExecute functionality. Once we extend this idea to
embrace multiple events, CanExecute functionality starts to become a
little murky, at best. Without CanExecute, you may just as well be
dealing with a delegate instead of an ICommand.”
So I decided to add support for this. Basically this feature enables you to expose a Delegate (of type Action<object> ) as a property in the ViewModel which would be called when the specified event is raised. Something like this
and the ViewModel property would look like this
As you can see in the example you can still use the CommandParameter attached property and it will be passed to you when the delegate is called.
I think that these 2 features add a lot to the ACB. I quite happy with what I achieved here and I hope that this library will also help you. Any feedback comments bug reports are most welcome
WARNING: This code was not tested a lot so expect bugs etc… If you want to use this in production code you are doing so at your own risk yet I must say it works on my machine …. hehe
The WPF Commands are really a cool and powerful tool that really help when you are trying to separate concerns by using patterns such as M-V-VM. If you haven’t had a look at my previous post on the ICommand I suggest that you do that before reading this post.
The only thing that I see a bit limited is the fact that you can use Commands only when a control implements the ICommandSource (such as ButtonBase etc). Well to say the truth you can still use commands if a Control does not implement ICommandSource but you have to do some plumbing yourself. Another problem that I see is that when a control implements the ICommandSource you are bound to the fact that the command will get executed according to the event being hooked up in the control implementation of ICommandSource, for example in case of a Button the Command would be executed when the Click event is raised. But what if you don’t want to execute a command when the Click event is fired, what if you want a command to be fired when the MouseRightButtonDown… One of my favorite WPF gurus, John Gossman blogged on this, read his post here.
I really love this approach yet you have to create an AttachedProperty for every different event you want to hook to.
It would be nice if you could supply the name of an Event in an AttachedProperty and the rest is done for you, i.e calling the Command when the event is fired… something like this….
What are the benefits of such an approach
1. Hook a Command to any Event and any control
2. You can change the event to which a command is hooked at runtime
3. You can Databind the Command, the CommandParameter and also the Event which will execute your Command (This is shown in the demo by binding the event to a combobox populated with event names.
This solution would not only let the ViewModel control what is shown in the View but also control the Behavior of the UI if needed.
With this the ViewModel now has the power to control also the behavior of the the UI !
And here comes the AttachedCommandBehavior
I had some spare time to play around with this and I wrote a small prototype for this. My implementation consists of a 3 Attached properties where the user can specify the Event, Command and CommandParameter. Once these properties are set the hooking of the event is done automatically so that when the specified event is fired the Command is called. Here is a breakdown of the classes I created…
Defines the Attached properties to be used on a control that need to hook an event to a Command.
Properties you will be using to set up a CommandBehavior
This is a private property that is used internal to create the CommandBehaviorBinding
This is an attached property that stores the Event name (as a string) for the Event you want to hook.
This is an attached property that stores the instance of the ICommand you want to execute when the event (specified in the Event property) is raised
This is an attached property that stores the object that you want to pass as parameter to the Command being executed
Defines the binding between an event and a command. This entity is also responsible of executing the command when the event is raised
Static class that is able to create a method at runtime that has the same signature as the EventHandlerType of the Event so that we can register to any kind of event. PLEASE NOTE: This uses Reflection and also DynamicMethod which construct the IL for the event handler at runtime!
The code is very simple. All we are doing here is to create an event handler at runtime that has the same signature as the Event type. The EventHandler that we create on runtime calls a method of the CommandBehaviorBinding that executes the Command. By using reflection we get the EventInfo of the EventName set in the Attached property and hook the EventHandler we created at runtime to the Event. That’s basically it.
I think the best thing to do here is to have a look at the source code I provided in this post and see how it all works out.
You can specify the event name and the Command by doing something like this
Here we are stating that when the MouseDown event is raised on the Border the SomeCommand should execute. Simple enough…
But we can do much more… We can also make the event dynamic…. something like this…
So here what we are doing is bind the Event attached property to the selected item in the ComboBox (The combobox is populated with a list of Event names that the border exposes). So when the user changed the selection of the ComboBox the Command will start being executed when the newly selected event is raised, which CommandBinding dynamic
- You can only hook to Events that have a Delegate of type void (for example EventHandler). I did this by design not to over complicate the generation of the dynmaic EventHandler + because most events for controls are all void.
- This solution uses Reflection so it cannot be used in XBAPs because of the security restrictions there are in XBAPs
This is just a prototype that I have built in a couple of hours… nothing really fancy… I did not do a lot of testing on this so please keep that in mind if you are gonna use this in a production environment. I really like this solution because it is really flexible and makes the use of Commands more easy for any kind of Control and any kind of Event! No more code behind to hook up events
One thing I did not add is the support for the CanExecute. I was not sure if it really makes sense in this context… Yet if you want to add it, it’s really easy all you have to do is handle the Command’s CanExecuteChanged event and call the CanExecute there
Hope you like this… Looking forward to hear feedback