Home > WPF > Declaring Custom WPF Commands via MarkupExtensions

Declaring Custom WPF Commands via MarkupExtensions

April 25th, 2009

And yet another markup extension that hopefully makes things a little easier for you. Basically, it’s the same pattern that the good doctor described here for value converters, but with custom commands in mind.

Without Extension

Basically, this extension makes your commands immediately available without having to declare them. One "traditional" way to declare a command is directly in XAML:

<Window.Resources>

  <cmd:HelloWorldCommand x:Key="SayHello" />

</Window.Resources>

 

…and then apply it like this:

<Button Command="{StaticResource SayHello}" />

 

Using the Markup Extension

The declaration part above can become somewhat tedious, especially if you have quite a few commands (e.g. because you are using a ribbon with lots of buttons on it). Thanks to using a markup extension, you can skip the declaration part altogether and just declare your command.

<Button Command="{cmd:HelloWorldCommand}" />

 

Implementation and Sample

 

/// <summary>
/// Basic implementation of the <see cref="ICommand"/>
/// interface, which is also accessible as a markup
/// extension.
/// </summary>
public abstract class CommandExtension<T> : MarkupExtension, ICommand
    where T:class, ICommand, new()
{
  /// <summary>
  /// A singleton instance.
  /// </summary>
  private static T command;


  /// <summary>
  /// Gets a shared command instance.
  /// </summary>
  public override object ProvideValue(IServiceProvider serviceProvider)
  {
    if (command == null) command = new T();
    return command;
  }


  /// <summary>
  /// Fires when changes occur that affect whether
  /// or not the command should execute.
  /// </summary>
  public event EventHandler CanExecuteChanged
  {
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
  }
  

  /// <summary>
  /// Defines the method to be called when the command is invoked.
  /// </summary>
  /// <param name="parameter">Data used by the command.
  /// If the command does not require data to be passed,
  /// this object can be set to null.
  /// </param>
  public abstract void Execute(object parameter);


  /// <summary>
  /// Defines the method that determines whether the command
  /// can execute in its current state.
  /// </summary>
  /// <returns>
  /// This default implementation always returns true.
  /// </returns>
  /// <param name="parameter">Data used by the command.  
  /// If the command does not require data to be passed,
  /// this object can be set to null.
  /// </param>
  public virtual bool CanExecute(object parameter)
  {
    return true;
  }
}

 

…and here’s a sample implementation:

public class HelloWorldCommand : CommandExtension<HelloWorldCommand>
{
  public override void Execute(object parameter)
  {
    MessageBox.Show("Hello world.");
  }
}

 

Of course, nothing prevents you from pimping the base class a little to your needs :-)


Author: Categories: WPF Tags: ,
  1. April 30th, 2009 at 10:01 | #1

    Nice article, thx !

  2. April 30th, 2009 at 17:59 | #2

    Cheers, Jmix :)

  3. Amir
    May 14th, 2009 at 21:16 | #3

    Don’t make the singleton. Don’t make the base class generic and have the ProvideValue(){ return this; }

    Simpler.

  4. Eug
    May 20th, 2009 at 02:56 | #4

    @Amir

    I agree.

    It’s not really a true singleton either, since the framework will instantiate a HelloWorldCommand object just to return the supposed singleton.

  5. May 20th, 2009 at 07:45 | #5

    Amir and Eug,

    There’s nothing wrong with returning a new instance every time – both solutions work – the “pseudo-Singleton” just is a bit more resource-friendly, as the markup-extension lives only for a very short period. Furthermore, I like the fact that the MarkupExtension part (creating and returning an object) is separated from the converter logic (imagine MarkupExtension would implement IDisposable in WPF4 and being disposed after having called ProvideValue…)

    I frankly don’t see a reason *not* to use that solution – the implementation is a bit more “complex”, but from the user’s point of view, there’s no difference if implemented properly.

    But as I said – if you feel like removing that part, there’s nothing wrong with that, either. After all, this is about simplified declaration rather than managing system resources :)

  6. September 2nd, 2014 at 11:24 | #6
  1. No trackbacks yet.