Search code examples
c#wpfrouted-commands

Executed gets not called after PreviewExecuted


Here's my code:

var commandBinding = new CommandBinding(ApplicationCommand.New);
commandBinding.PreviewExecuted += OnPreviewExecuted;
commandBinding.Executed += OnExecuted;
CommandBindings.Add(commandBinding);

void OnPreviewExecuted(object sender, ExecutedRoutedEventArgs e) {
  e.Handled = false;
}

void OnExecuted(object sender, ExecutedRoutedEventArgs e) {
  DoSomething();
}

MSDN says:"...If the preview event is not handled, the Executed event is raised on command target."

This does work correctly for the PreviewCanExecute event. But in this case the Executed-Event will not get called when a PreviewExecuted-Event is listening.

I did not find anything around this topic so I want to ask, whether the behavior is intended or just incorrect.


Solution

  • It seems it doesn't matter what you set e.Handled to.

    Here is the code that decides which events to raise (ExecuteImpl in RoutedCommand.cs):

    ExecutedRoutedEventArgs args = new ExecutedRoutedEventArgs(this, parameter);
    args.RoutedEvent = CommandManager.PreviewExecutedEvent;
    
    if (targetUIElement != null)
    {
        targetUIElement.RaiseEvent(args, userInitiated);
    }
    else
    {
        ...
    }
    
    if (!args.Handled)
    {
        args.RoutedEvent = CommandManager.ExecutedEvent;
        if (targetUIElement != null)
        {
            targetUIElement.RaiseEvent(args, userInitiated);
        }
        ...
    }
    

    So indeed, if e.Handled is false after the preview event, the Executed event should be raised. But it is never false after a PreviewExecuted handler is invoked (CommandBindings.cs, OnExecuted):

    PreviewExecuted(sender, e);
    e.Handled = true;
    

    It simply sets e.Handled to true after invoking the preview handler...

    Why this is so, I have no idea. PreviewCanExecute works the same way, but it only sets e.Handled to true if e.CanExecute is set to true - if you do that in your preview handler, the CanExecute handler won't be called regardless of e.Handled.

    My assumption is that "If the preview event is not handled" is an unfortunate wording of "If the preview event does not have a registered handler".