AttachedCommandBehavior V2 aka ACB
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
1: <Border Background="Yellow" Width="350" Margin="0,0,10,0" Height="35" CornerRadius="2" x:Name="test">
2: <local:CommandBehaviorCollection.Behaviors>
3: <local:BehaviorBinding Event="MouseLeftButtonDown" Action="{Binding DoSomething}" CommandParameter="An Action on MouseLeftButtonDown"/>
4: <local:BehaviorBinding Event="MouseRightButtonDown" Command="{Binding SomeCommand}" CommandParameter="A Command on MouseRightButtonDown"/>
5: </local:CommandBehaviorCollection.Behaviors>
6: <TextBlock Text="MouseDown on this border to execute the command"/>
7: </Border>
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
1: <Border Background="DarkSalmon" Width="350" Margin="0,0,10,0" Height="35" CornerRadius="2"
2: local:CommandBehavior.Event="MouseDown"
3: local:CommandBehavior.Action="{Binding DoSomething}"
4: local:CommandBehavior.CommandParameter="from the DarkSalmon Border"/>
and the ViewModel property would look like this
1: DoSomething = x => Messages.Add("Action executed: " + x.ToString());
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.
Conclusion
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





Cool dude
– This can be VERY useful – ACB is much more muscular now!!
[...] Marlon Grech on AttachedCommandBehavior V2 aka ACB [...]
Pingback by 2008 December 15 - Links for today « My (almost) Daily Links | December 16, 2008 |
I’m wondering if there’s a way to get the control to disable or enable when using either an action or command binding?
In the sample there is a SimpleCommand “ClearMessagesCommand” that is bound to a button the “usual” way:
But I would like to be able to bind the command to other events on the button like MouseDown / MouseOver etc. AND have the control disable.
Is there a way to extract the “CanExecute” return value like this:
<Button IsEnabled=”{Binding
ClearMessagesCommand.CanExecute}”
Next version of ACB will have a lot of these things
just give me some time
[...] my purposes. I must credit Mike Hillberg and his MethodCommand solution and Marlon Grech and his Attached Command Behaviors solution for guidance and inspiration as I waded into [...]
Pingback by MethodCaller: Invoking Methods betwen the View and the ViewModel « My Development KB | February 14, 2009 |
[...] 2 http://groups.google.com/group/wpf-disciples/browse_thread/thread/63cbe8b2b0575e4e?pli=1 3: http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/ a smart way to use double click [...]
Pingback by attached property « Steveluo’s Blog | February 24, 2009 |
[...] some time and build a WPF sample application to showcase the use of MVVM + Mediator and also how AttachedCommandBehaviours can be used to further reduce (or better eliminate) C# code in XAML code behind files. I am also [...]
Pingback by [MVVM + Mediator + ACB = cool WPF App] – Intro « C# Disciples | April 2, 2009 |
Hi Marlon,
I recently study your ACB.
it is a very good idea.
and it also my problems.
but,…
I found a case fails ACB.
it is about routed command and foucs.
I use ACB on a border and assign a command react on boder’s MouseDown event.
If the focus is not on the view of this border, the command can not route to it’s view, but can route to it’s parent view.
Do you have any idea about this issue, thank you.
I didn’t quite understand … can you re explain please
Hi Marlon
There is a sample code for my issue,
http://caa.myweb.hinet.net\MyACBSample.zip
There are only one window and one view in this project,and
this view only contains one button and one border.
If the focus not on viewButton,
“Mouse Down” on border1 can not execute command.
but after click viewButton, it works(pop a message).
I also try to listen MouseDown event of border1 and execute command in the event handler in code behind, it works too.
I don`t realize why ACB Command could not work in this case.
Thanks for your comment, and this is a much useful method.
I don’t think this has anything to do with ACB it just how the routed events work…
Try using PreviewMouseDown. I think that would work for you.
P.S couldn’t download the file you sent… was saying Error 404
[...] http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/ [...]
Pingback by [WPF] Comment actionner une commande WPF lorsqu’un évènement est déclenché ? , Thomas Lebrun | April 14, 2009 |
Great solution, but if Event that i need to route send for me EventArgs?
Can i bind event “EventArgs” to CommandParameter? And how can i do that?
not with the current implementation… sorry
Well, maybe you give me some tricks for modify EventHandlerGenerator.CreateDelegate method to support CommandBehaviorBinding.Execute with parameters? I’m not full understand ILGeneration there, but you are read all parameters from eventHandlerInfo, so may be this parameters can be binded to some parameters in Execute method?
For example:
public void Execute(object parameter)
{
if(CommandParameter == null)
{
strategy.Execute(parameter);
}
else
{
strategy.Execute(CommandParameter);
}
}
where “object parameter” is event EventArgs…
I’ll have to look into this…. because it is not that easy….
Thanks! This will be great, if it possible
[...] should state that this post was inspired by a good friend of mine Marlon Grechs AttachedCommandBehavior V2 aka ACB blog post. I loved and have used Marlons idea, but he uses dynamically created IL, to create the [...]
Pingback by sachabarber.net » WPF : Attached Commands | May 2, 2009 |
Damn, yeah! I’m merge ACB V2 and info from sachabarber.net, and this is it! Now i can bind command parameter, or hook EventArg’s! Thnx so much!
What i’m change:
1) Delete EventHandlerGenerator class.
2) Delete CommandBehaviorBinding.Execute method.
3) Update CommandBehaviorBinding.BindEvent method to this:
public void BindEvent(DependencyObject owner, string eventName)
{
EventName = eventName;
Owner = owner;
Event = Owner.GetType().GetEvent(EventName, BindingFlags.Public | BindingFlags.Instance);
if (Event == null)
throw new InvalidOperationException(String.Format(”Could not resolve event name {0}”, EventName));
//Register the handler to the Event
EventHandler = Delegate.CreateDelegate(Event.EventHandlerType, this,
GetType().GetMethod(”OnEventRaised”,
BindingFlags.NonPublic |
BindingFlags.Instance));
Event.AddEventHandler(Owner, EventHandler);
}
4) Add OnEventRaised method to CommandBehaviorBinding class:
///
/// Runs the ICommand when the requested RoutedEvent fires
///
private void OnEventRaised(object sender, EventArgs e)
{
if (Command != null)
{
if(CommandParameter != null)
{
Command.Execute(CommandParameter);
}
else
{
Command.Execute(e);
}
}
}
5) Enjoy and have fun
it is really greate!!
I saw your idea and clever implementation of it.
Thank you~~ ^^
And little more… If we bind CommandParameter to some item. And on some event we need to take this item or null value? So, with this implementation we will take binded item, or event args… This method is little wrong
I resolve this problem like this:
1) In CommandBehaviorBinding replace CommandParameter property to this:
///
/// Gets or sets a CommandParameter
///
private object commandParameter;
public object CommandParameter
{
get
{
return commandParameter;
}
set
{
commandParameter = value;
IsCommandParameterBinded = true;
}
}
2) Add IsCommandParameterBinded property to CommandBehaviorBinding:
protected bool IsCommandParameterBinded { get; set; }
3) Update OnEventRaised method in CommandBehaviorBinding to this:
///
/// Runs the ICommand when the requested RoutedEvent fires
///
private void OnEventRaised(object sender, EventArgs e)
{
if (strategy != null)
{
if (IsCommandParameterBinded)
{
strategy.Execute(CommandParameter);
}
else
{
strategy.Execute(e);
}
}
}
So now, if we bind CommandParameter we will take only CommandParameter values. If not, we will hook EventArg’s. I’m not sure about replacing “Command” to “strategy” there, but I’m do that.
Marlon, may be you collect this changes to next version and fix our misunderstanding about Command and strategy in CommandBehaviorBinding?
[...] http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/ [...]
Pingback by kevin Mocha - AttachedCommandBehavior V2 aka ACB | May 29, 2009 |
visit us!
newsbox.cc
newsbox.us
nbstatus.wordpress.com
NOW!