0

I know there are a handful of related questions but none of those helped me finding the issue.

Most answers suggest to implement CanExecuteChanged as shown in this answer. Well, that's not the solution to my problem. I've got an implementation of RelayCommand similar to Josh Smith's implemenation. (Similar, because our implementation adds more details but the core implementation is the same.)

While searching the Internet I also learned that if there is no focused element, the routing will stop at the ContextMenu and wouldn't reach the MenuItem. A solution that would help in that case is shown here.
However, I checked with Snoop if there really isn't any focused element and learned this is not the issue. And the fix didn't help anyway.
Besides, I simulated that issue in a test project and was able to fix it. So the fix generally works, it's just not helping me. I think there's still a chance, however, that I have to adapt the fix slightly to get it working. I tried MyControl instead of ContextMenu as AncestorType and I tried PlacementTarget.Tag instead of just PlacementTarget as Path but I wouldn't know what else to try to get it working (assuming that this is the bug).

Funny enough, it even doesn't work when I call CommandManager.InvalidateRequerySuggested() manually. I added a command that is raised on ContextMenuOpening. I thought that this would force the CanExecute to be executed but it seems I'm mistaken.

So, I'm now looking for further reasons why a CanExecute handler isn't raised when a ContextMenu is opened and how I would fix that.

Here's my XAML code (including EventTrigger for ContextMenuOpening):

<MyControl>
  <MyControl.ContextMenu>
    <ContextMenu>
      <MenuItem Header="..."
                Command="{Binding MyCommand}"
                CommandParameter="{Binding}"
                CommandTarget="{Binding Path=PlacementTarget,
                  RelativeSource={RelativeSource
                    AncestorType={x:Type ContextMenu}}}"/>
    </ContextMenu>
  </MyControl.ContextMenu>
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="ContextMenuOpening">
      <i:InvokeCommandAction Command="{Binding OnContextMenuOpening}" />
    </i:EventTrigger>
  </i:Interaction.Triggers>
</MyControl>

Here's the definition of MyCommand and the (Can)Execute handlers:

internal static readonly ICommandEx MyCommand = 
  new RelayCommand(OnMyCommand, OnCanMyCommand);

private static void OnMyCommand(object parameter) { ... }

private static bool OnCanMyCommand(object parameter) { ... }

Here's my OnContextMenuOpening handler where I tried to force MyCommand's CanExecute to be raised:

private static void OnContextMenuOpening(object parameter)
{
  CommandManager.InvalidateRequerySuggested();
}
Community
  • 1
  • 1
Em1
  • 1,077
  • 18
  • 38
  • I don't feel lokusking's answer would help. Read this for reference http://stackoverflow.com/questions/17176092/wpf-canexecute-constantly-requerying – Akanksha Gaur Jun 23 '16 at 11:14
  • Can you ensure that Binding work? e.g the command can be executed regardless the CanExecute. Does the CanExecute need the command parameter to 'decide'? Can you ensure that parameter in not null?. Does your RelayCommand work correctly in any other case e.g simple button? – Athafoud Jun 23 '16 at 12:59
  • @Athafoud I should've mentioned that I use the same command for a button in a toolbar and CanExecute works fine. Regarding my context menu, the binding definitely works. – Em1 Jun 23 '16 at 13:09

1 Answers1

0

You are incorrectly listening on OnContextMenuOpening on the ContextMenu control. It will never fire! Instead, listen on this very event on your MyControl control.

l33t
  • 18,692
  • 16
  • 103
  • 180