Avoiding CommandBinding in the XAML Code Behind files

Yesterday I got a very good question from a colleague. Basically we were discussing the M-V-VM pattern and how it makes your XAML code behind much cleaner + your application more testable. The only thing that was annoying him was the fact that he had to do the command binding and delegate the work to the ViewModel . So he asked me, “Is there a way how I can remove the Command Binding from my code behind as well?”. What he was referring to, was the hooking of Commands to the ViewModel, which would look something like this

   1: CommandBindings.Add(
   2:     new CommandBinding(Commands.Search,
   3:     (x, e) => vm.Search(),
   4:     (x, e) => e.CanExecute = vm.CanSearch())
   5:     );

And the answer is, of course you can! After all, is there something you cannot do with the mighty WPF :P

So how can we achieve this? We have to create a class that implements the ICommand interface. Here is how the ICommand interface looks like.

   1: public interface ICommand
   2: {
   3:     event EventHandler CanExecuteChanged;
   4:  
   5:     bool CanExecute(object parameter);
   6:  
   7:     void Execute(object parameter);
   8: }

Very simple isn’t it! Here is the MSDN description of the methods of this interface

ms616874.pubmethod(en-us,VS.90).gif
CanExecute
Defines the method that determines whether the command can execute in its current state.

ms616874.pubmethod(en-us,VS.90).gif
Execute
Defines the method to be called when the command is invoked.

ms616874.pubevent(en-us,VS.90).gif
CanExecuteChanged
Occurs when changes occur that affect whether or not the command should execute.

So in the CanExecute we have to put the logic that checks if we can execute the command and in the Execute we put the logic that executes the command…. but what about the CanExecuteChanged event? Well here we have to hook up to the Command System. Here is a simple implementation of the ICommand.

   1: public class SearchCommand : ICommand
   2: {
   3:     ViewModel viewModel;
   4:     public SearchCommand(ViewModel viewModel)
   5:     {
   6:         this.viewModel = viewModel;
   7:     }
   8:  
   9:     #region ICommand Members
  10:  
  11:     public bool CanExecute(object parameter)
  12:     {
  13:         return !String.IsNullOrEmpty(viewModel.SearchText);
  14:     }
  15:  
  16:     public event EventHandler CanExecuteChanged
  17:     {
  18:         add { CommandManager.RequerySuggested += value; }
  19:         remove { CommandManager.RequerySuggested -= value; }
  20:     }
  21:  
  22:     public void Execute(object parameter)
  23:     {
  24:         viewModel.MyDataView.Filter = x => ((Person)x).Name.Contains(viewModel.SearchText);
  25:     }
  26:  
  27:     #endregion
  28: }

  As you can see in order to hook up to the WPF command system we have to override the default behavior of the event and register to the CommandManager.RequerySuggested like so

   1: public event EventHandler CanExecuteChanged
   2: {
   3:     add { CommandManager.RequerySuggested += value; }
   4:     remove { CommandManager.RequerySuggested -= value; }
   5: }

This is very important because by doing so the CanExecute method will be called when ever there is focus changed, user input etc…

Once you have a class that implements the ICommand you can expose that class in your ViewModel and databind to it in the Command property of the control you want to hook up the command to like so

   1: ViewModel property
   2: /// <summary>
   3: /// Return an ICommand that can execute the search
   4: /// </summary>
   5: public ICommand SearchByNameCommand
   6: {
   7:     get { return searchByNameCommand; }
   8: }
   9:  
  10: XAML to hook to that command
  11: <Button Command="{Binding SearchByNameCommand}" Content="Search" />

And that’s it… No more command bindings to hook to the Command in the code behind of the XAML file! This is very cool but now I guess the next question would be, so we actually have to create a class and implement an ICommand every time??

Well the answer is HELL NO…. What I do is create a class that does all the stuff for me and then I pass a delegate for the CanExecute and another one for the Execute… as simple as this…

   1: public class SimpleCommand : ICommand
   2: {
   3:     public Predicate<object> CanExecuteDelegate { get; set; }
   4:     public Action<object> ExecuteDelegate { get; set; }
   5:  
   6:     #region ICommand Members
   7:  
   8:     public bool CanExecute(object parameter)
   9:     {
  10:         if (CanExecuteDelegate != null)
  11:             return CanExecuteDelegate(parameter);
  12:         return true;// if there is no can execute default to true
  13:     }
  14:  
  15:     public event EventHandler CanExecuteChanged
  16:     {
  17:         add { CommandManager.RequerySuggested += value; }
  18:         remove { CommandManager.RequerySuggested -= value; }
  19:     }
  20:  
  21:     public void Execute(object parameter)
  22:     {
  23:         if (ExecuteDelegate != null)
  24:             ExecuteDelegate(parameter);
  25:     }
  26:  
  27:     #endregion
  28: }

and to create a command now is as simple as this…

   1: searchByNameCommand = new SimpleCommand
   2: {
   3:     CanExecuteDelegate = x => !String.IsNullOrEmpty(SearchText),
   4:     ExecuteDelegate = x => myDataView.Filter = stateObj => ((Person)stateObj).Name.Contains(SearchText)
   5: };

and yes you could say that it is a 1 line of code :P (well a long one maybe :) )… yet of course, you can have as much logic in there as you want!

 

If you want to see a sample project I created a demo app that you can download here.

kick it on DotNetKicks.com

About these ads

21 thoughts on “Avoiding CommandBinding in the XAML Code Behind files

  1. This is a nice article Marlon. I saw a very similar approach on a Model View ViewModel video a couple last week.
    My question is, how do you handle input gestures with this technique ? How do you do to associate a shortcut to your command ?

  2. Jeremy that is really a good question … yet I am not able to answer it today because I never did that… when ever I needed that I relied on the Routed Commands…. a good next post I must say :P

  3. Pingback: 2008 November 27 - Links for today « My (almost) Daily Links

  4. Pingback: Dew Drop - November 28, 2008 | Alvin Ashcraft's Morning Dew

  5. Pingback: Visual Studio Links #86 : Visual Studio Hacks

  6. Pingback: AttachedCommandBehavior aka ACB « C# Disciples

  7. Pingback: Keep code behind clean « The Simple Part

  8. Anyone know how to write that CanExecuteChanged EventHandler in Vb.net code?

    ie.
    public event EventHandler CanExecuteChanged
    {add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; }
    }

  9. Pingback: Behaviour driven development on user interfaces with Automation peer « The Simple Part

  10. Pingback: The power of ICommand - Rudi Grobler

  11. Pingback: [MVVM + Mediator + ACB = cool WPF App] – The MVVM « C# Disciples

  12. Pingback: sachabarber.net » WPF : Attached Commands

  13. Pingback: WPF ICommand vs RoutedCommand | Grimcoder blog

  14. That CanExecuteChanged implementation bothers me a bit — CommandManager.RequerySuggested is documented as only holding a weak reference to attached handlers. Which suggests that it wouldn’t work reliably in this case.

  15. Thanks so much for the great post. It removes most of the junk that we have to create a command binding in WPF. But in real application, the anonymous functions which are used as Predicate and Action are not realistic. Most of the time I have to use a function instead :)

    But this is really a nice post. I’ve learned a lot from this :)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s