Declaring Custom WPF Commands via MarkupExtensions
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 ๐
Nice article, thx !
Cheers, Jmix ๐
Don’t make the singleton. Don’t make the base class generic and have the ProvideValue(){ return this; }
Simpler.
@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.
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 ๐
the correct link to DrWPF’s article is:
http://drwpf.com/blog/2009/03/17/tips-and-tricks-making-value-converters-more-accessible-in-markup/