WPF Commanding – When do Commands re-evaluate their CanExecute method?

I had been merrily using WPF’s built-in support for the Command Pattern for ages (see Commanding Overview, MSDN Docs, and article on implementing the command pattern in WPF, Jeff Druyt)… when suddenly it occured to me that I had no idea what triggered WPF to determine whether or not a command can be executed.

Let me explain by reduction to an absurd example:

Say I have a command that can only execute when

DateTime.Now.Second % 2 == 0.

I construct this command by home-brewing a static RoutedCommand instance:

public static class Commands

{

public static RoutedCommand MyCommand { get { return m_MyCommand; } }

private static RoutedCommand m_MyCommand = new RoutedCommand

(

“Execute My Command”,

typeof(Commands),

new InputGestureCollection()

{

new KeyGesture(Key.C, ModifierKeys.Alt)

}

);

}

And then I add a Command Binding for that command to my Window, and assign the command to a Button:

<Window x:Class=”TestCommands.Window1″…>
<Window.CommandBindings>
<CommandBinding
Command=”{x:Static local:Commands.MyCommand}”
Executed=”MyCommandExecuted”
CanExecute=”MyCommandCanExecute”
/>
</Window.CommandBindings>

<Button Width=”200″ Height=”200″
Command=”{x:Static local:Commands.MyCommand}”
Content=”{Binding Path=IsEnabled}”
/>

</Window>

By nature of WPF’s awesomeness and WPF Commanding in general, the above Button’s IsEnabled property should automatically be set to true or false based on whether or not the command can or can’t be executed.

Speaking of which, let’s set up my Command’s absurd logic in the CodeBehind by implementing its Execute and CanExecute event handlers:

private void MyCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)

{

DateTime now = DateTime.Now;

if (CanExecuteOutput != null)

{

CanExecuteOutput.Text = “MyCommand CanExecute determined at “ +

now.ToLongTimeString() + ” (and “ + now.Millisecond + “ms)”;

}

e.CanExecute = DateTime.Now.Second % 2 == 0;

}

private void MyCommandExecuted(object sender, ExecutedRoutedEventArgs e)

{

TextOutput.Text = “MyCommand executed at “ + DateTime.Now.ToLongTimeString();

}

So, my example is absurd but I bet you see my point by now: WPF is meant to automatically set the IsEnabled Property on that button to true or false, based on the results of the CanExecute method. But in this case, the results of CanExecute are a function only of time, and thus change repeatedly and independently of “obvious” application events. So… how does the Commanding system know when to query CanExecute and consequently enable/disable the button once a second?

In this case, without further intervention, it doesn’t. It seems that when events are raised on the Window (a mouse button click, etc.), CanExecute is re-evaluated. (I don’t know the details and wish I did.)  But, without further programmatic or user intervention, the button will not automatically change its IsEnabled state once a second.

This led me back to the MSDN docs, where I discovered the aptly-named InvalidateRequerySuggested event. To coerce – er, suggest – that WPF should query CanExecute, I set up the following DispatcherTimer:

m_DispatcherTimer = new DispatcherTimer()

{

Interval = TimeSpan.FromSeconds(0.25),

IsEnabled = true

};

m_DispatcherTimer.Tick += delegate

{

CommandManager.InvalidateRequerySuggested();

};

Now, the IsEnabled property of the Button blinks on and off as the Command’s ability to be executed changes with the passing seconds.

Only then did I discover there’s an MSDN Docs sample called “Disable Command Source Via Dispatcher Timer Sample” which is remarkably similar.

There you have it. Now go forth and command WPF’s Commanding. I’m sure you can all execute on that request <g>

P.S. Code for this sample is here.

P.P.S. What are folks using for pasting XAML and C# code into their blogs? This entry is looking a little rough…