none
Why is my ContextMenu item disabled? RRS feed

  • Question

  • Can someone please tell me why, in the following window:

    Code Block

    <Window x:Class="GuitarHelper.Main" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:GuitarHelper"
            Title="GuitarHelper™" Width="450" Height="150" WindowStyle="SingleBorderWindow" Icon="Resources/GuitarHelper.ico"
            MouseDown="Window_MouseDown">
        <Window.CommandBindings>
            <CommandBinding Command="ApplicationCommands.Open" Executed="Open_Executed" CanExecute="Open_CanExecute" />
        </Window.CommandBindings>
        <Window.ContextMenu>
            <ContextMenu>
                <ContextMenu.Items>
                    <MenuItem Command="ApplicationCommands.Open" />
                </ContextMenu.Items>
            </ContextMenu>
        </Window.ContextMenu>
        <StackPanel>
            <Menu>
                <MenuItem Header="_File">
                    <MenuItem Command="ApplicationCommands.Open" />
                </MenuItem>
            </Menu>
        </StackPanel>
    </Window>



    ...the Open command in the menu bar is enabled, while the Open command in the ContextMenu is disabled??
    Thursday, November 22, 2007 3:28 AM

Answers

  • This is a known bug. If there is no focused element in the window's main focus scope, the CanExecute routing will stop at the ContextMenu, so it will not reach to the CommandBinding on the Window, one workaround is to bind MenuItem's CommandTarget to the main window, as following code demonstrates:

     

    Code Block

     

    <Window.ContextMenu>

        <ContextMenu >

          <ContextMenu.Items>

            <MenuItem Command="ApplicationCommands.Open"

                      CommandTarget="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>

          </ContextMenu.Items>

        </ContextMenu>

      </Window.ContextMenu>

    Hope this helps
    Monday, November 26, 2007 9:47 AM

All replies

  • This is a known bug. If there is no focused element in the window's main focus scope, the CanExecute routing will stop at the ContextMenu, so it will not reach to the CommandBinding on the Window, one workaround is to bind MenuItem's CommandTarget to the main window, as following code demonstrates:

     

    Code Block

     

    <Window.ContextMenu>

        <ContextMenu >

          <ContextMenu.Items>

            <MenuItem Command="ApplicationCommands.Open"

                      CommandTarget="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>

          </ContextMenu.Items>

        </ContextMenu>

      </Window.ContextMenu>

    Hope this helps
    Monday, November 26, 2007 9:47 AM
  • Perhaps a solution I found for my problem might help. Essentially I had to make sure the current focus was in some way related to the ContextMenu's visual/logical parent, which then allows the Command Routing to work correctly.

     

    Article here: http://forums.microsoft.com/Forums/ShowPost.aspx?PostID=2854165&SiteID=1&mode=1

    Friday, February 15, 2008 11:23 PM
  • Hi,

    Could you translate your solution in Csharp ?  I did bind the CommantTarget of my MenuItems to the containing window but all the items in the context menus are still disabled.

    Here's a hint though: this window is instantiated dynamically with the activator class. When I instantiate the same window as the startup URI in the App.xml file, the context menu is enabled.

    Anyone has a clue ??

    Web Developer
    Monday, February 23, 2009 7:15 AM
  • Boy. I just struggled with this one for about an hour. Am I stupid or is this still not fixed ?
    BTW: I used http://www.wiredprairie.us/journal/2007/04/commandtarget_menuitem_context.html as a solution.
    Thursday, August 6, 2009 2:34 PM
  • Thank you very much, very useful!!!
    Thursday, August 12, 2010 3:55 PM
  • Actually this wasn't completely it as Marco Zhou's post wasn't compiling for me. I agree this was really frustrating me for awhile. Mine was a little bit more tricky as it was a command for a custom WPF object I created. Here is what I had to use to get it to work via XAML:

     

    <MyNamespace:CustomCanvas.ContextMenu>
         <ContextMenu>    
              <MenuItem Command="{x:Static MyNamespace:CustomCanvas.CustomView}"
                       Header="Custom View"
                       CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
              </MenuItem>
         </ContextMenu>
    </MyNamespace:CustomCanvas.ContextMenu>
    


    Then in my class in code behind:

     

     

        public partial class CustomCanvas: Canvas
        {
            public static RoutedCommand CustomView = new RoutedCommand();
    
            public CustomCanvas()
            {
                this.CommandBindings.Add(new CommandBinding(CustomCanvas.CustomView , DoCustomView , canCustomView ));
            }
    
            public void DoCustomView(object sender, ExecutedRoutedEventArgs e)
            {
                App.customMode = true;
            }
    
            public void canCustomView(object sender, CanExecuteRoutedEventArgs e)
            {
                e.CanExecute = true;
            }
        }
    


    Alternatively instead of using the XAML, it can also be completely set up in code behind (dw4Ish, this should answer your question). For 100% code behind setup, add the following lines of code before you add your command bindings in the constructor. For example:

     

    var ctxMenu = new ContextMenu();
    var menu1 = new MenuItem { Header = "Cut", Command = ApplicationCommands.Cut, CommandTarget = this };
    var menu2 = new MenuItem { Header = "Copy", Command = ApplicationCommands.Copy, CommandTarget = this };
    var menu3 = new MenuItem { Header = "Paste", Command = ApplicationCommands.Paste, CommandTarget = this };
    
    ctxMenu.Items.Add(menu2);
    ctxMenu.Items.Add(menu3);
    ctxMenu.Items.Add(menu1);
    

     

    Hope this helps.

     

     


    • Edited by jbrumbau Monday, October 3, 2011 11:19 PM
    Monday, October 3, 2011 11:18 PM
  • Thanks so much for this solution.  I have no idea how long it would have taken for me to figure this out.
    Thursday, March 26, 2015 3:29 PM
  • I fixed this by simply focusing the control that owned the context menu when the right mouse button was pressed:

    private void MyListView_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ChangedButton == MouseButton.Right)
        {
            MyListView.Focus();
        }
    }

    • Proposed as answer by PwrGreg007 Friday, October 19, 2018 5:53 PM
    Saturday, June 11, 2016 11:34 PM
  • Thanks Nathan, that led me to a variation on your solution. I already intercept right-click to prevent it from (de)selecting items in the ListBox, so adding one line took care of the problem.

    void ListBoxMessages_PreviewRightMouseButtonDown(object sender, MouseButtonEventArgs e)
    {
    	// this line allows menu context/CanExecute... to work
    	listBoxMessages.Focus();
    	// this line disables (de)select so only left-click (de)selects
    	e.Handled = true;
    }
    


    • Proposed as answer by PwrGreg007 Friday, October 19, 2018 5:53 PM
    Friday, October 19, 2018 5:52 PM