Click here to Skip to main content
15,897,187 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am playing around with WPF and menus and I have a nested MenuItem in my menu. I know the adorners I have are ridiculous but it's just for learning. The question I have is that nested Command="ApplicationCommands.New", and Command="ApplicationCommands.Open" are always disabled and not selectable do I have to change the context? I googled looking for an answer but nothing I have read explains it yet. I am trying to figure out why they are greyed out and what is causing them to be greyed out. The code for the xaml and my codebehind are posted below. It is just a Menu sandbox so excuse the comments Thanks.


MY XAML MARKUP
HTML
<window x:class="WPF_Menus.MainWindow" xmlns:x="#unknown">
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <stackpanel>
        <menu>
            <menuitem header="File">
                <!--Adorned Menu Item New Game with an Image Can also set the IsChecked or IsCheckable Property.
                    Menus also contain and area for Keyboard shortcuts but they still need to be setup in the code behind.-->
                <menuitem header="New Game" click="MenuItemNewGame_Click" inputgesturetext="Alt+N">
                    <menuitem.icon>
                        <Image Source="Card.jpg"/>
                    </menuitem.icon>
                </menuitem>
                <!--Example of Other content as the Menu Header in this Case an Image-->
                <menuitem inputgesturetext="Alt+Q">
                    <menuitem.header>
                        <Image Source="Ace.jpg"/>
                    </menuitem.header>
                </menuitem>
                <!--MenuItem with Commands Attached. The Benefits are that the Text Header is automatically set,
                    The keyboard shortcut is filled with the appropriate string, and the command is hooked up so
                    if the user uses the MenuItem or the keyboard shortcut the command is executed. This assumes
                    that you've bound the command correctly in the code behind. I've made this a Nested MenuItem.-->
                <menuitem header="File">
                    <menuitem command="ApplicationCommands.New" />
                    <menuitem command="ApplicationCommands.Open" />
                </menuitem>
                <menuitem header="Exit" click="MenuItemExit_Click" />
            </menuitem>
            <menuitem header="Help" click="MenuItemHelp_Click" />
        </menu>
    </stackpanel>
</window>


MY CODE BEHIND
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPF_Menus
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            //Bindings for the Nested MenuItem's New and Open
            CommandBinding nBinding = new CommandBinding();
            nBinding.Command = ApplicationCommands.New;
            nBinding.Executed += DoNew_Executed;
            nBinding.CanExecute += DoNew_CanExecute;

            CommandBinding oBinding = new CommandBinding();
            oBinding.Command = ApplicationCommands.Open;
            oBinding.Executed += DoOpen_Executed;
            oBinding.CanExecute += DoOpen_CanExecute;
        }

        //Regular Menu Event Handlers
        private void MenuItemNewGame_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Clicked New Game", "Menu Info");
        }
        private void MenuItemExit_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Clicked Exit", "Menu Info");
        }
        private void MenuItemHelp_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Clicked Help", "Menu Info");
        }

        //Event handlers for the Nested MenuItem's New and Open.
        public void DoNew_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("New Command Executed", "Command Info");
        }
        public void DoNew_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }
        public void DoOpen_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("Open Command Executed", "Command Info");
        }
        public void DoOpen_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }
    }
}
Posted
Updated 24-Jul-13 4:12am
v3
Comments
Sergey Alexandrovich Kryukov 24-Jul-13 10:10am    
Do the "grayed-out items" just look gray, or are they actually disabled?
—SA
mark Dunham 24-Jul-13 10:12am    
They are actually disabled.
mark Dunham 24-Jul-13 10:40am    
But in the binding I do have it set as e.CanExecute = true; So wouldn't that mean my code is correct?
Sergey Alexandrovich Kryukov 24-Jul-13 10:45am    
Yes, I noticed that later... Then the reason is that the command-bound UI elements are disabled by default, and you failed to apply something to something. Honestly, no time to look into this detail... this is really simple. You created the instanced of bindings but forgot to include binding object them in your UI. Look for some code sample, it will be one more line (per binding object)...
—SA
mark Dunham 24-Jul-13 10:54am    
Thanks for the help found it and posted the solution. Appreciate it.

As you use the command binding, you are handling the event System.Windows.Input.CommandBinding.CanExecute and get System.Windows.Input.CanExecuteRoutedEventArgs passed to the handler. In the handler, you can assign a value to the Boolean property CanExecute. The UI invokes this event and finds out what to do with the the property System.Windows.UIElement.IsEnabled for the instances of the UIElement participated in the correspondent binding. Naturally, if you assign false (the command should not execute), the bound menu item is disabled.

Please see: http://msdn.microsoft.com/en-us/library/system.windows.input.commandbinding.canexecute.aspx[^],
http://msdn.microsoft.com/en-us/library/system.windows.input.canexecuteroutedeventargs.aspx[^],
http://msdn.microsoft.com/en-us/library/system.windows.input.canexecuteroutedeventargs.canexecute.aspx[^],
http://msdn.microsoft.com/en-us/library/system.windows.uielement.isenabled.aspx[^].

[EDIT]

And, to put it all to work, you forgot to add binding object to your UI. You also need Window.CommandBindings.Add. Please see, for example:
http://msdn.microsoft.com/en-us/library/system.windows.input.commandbinding.aspx[^].

—SA
 
Share this answer
 
v3
So with help from Sergey I figured this out. I was missing one line per each command binding that adds the binding to the binding list. I posted Just the binding code with the extra line below.

//Bindings for the Nested MenuItem's New and Open
CommandBinding nBinding = new CommandBinding();
nBinding.Command = ApplicationCommands.New;
nBinding.Executed += DoNew_Executed;
nBinding.CanExecute += DoNew_CanExecute;
this.CommandBindings.Add(nBinding);

CommandBinding oBinding = new CommandBinding();
oBinding.Command = ApplicationCommands.Open;
oBinding.Executed += DoOpen_Executed;
oBinding.CanExecute += DoOpen_CanExecute;
this.CommandBindings.Add(oBinding);
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 24-Jul-13 11:57am    
Sorry, but I would advise you to be careful about posting answers to your own question and especially self-accepting. It can easily be considered as abuse and reported against you. One problem is that some members badly abuse this opportunity and massively post those no-value questions followed by answers; some already lost their accounts for such things. I'm not reporting in this case, just advise to avoid it...
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900