I have an application that contains Menu and sub menus. I have attached Appliocation Commands to some of the sub menu items such as Cut, Copy and Paste.
I also have some other menu items that do not have application commands.
How could I add a custom command binding to those sub menu items?
I have gone through this article but unable to attach event to my sub menu items.
-
1Found this youtube link. youtube.com/watch?v=mG4l0AaYBTMSangram Nandkhile– Sangram Nandkhile2013-09-28 17:34:18 +00:00Commented Sep 28, 2013 at 17:34
3 Answers
I use a static class that I place after the Window1 class (or whatever the window class happens to be named) where I create instances of the RoutedUICommand class:
public static class Command {
public static readonly RoutedUICommand DoSomething = new RoutedUICommand("Do something", "DoSomething", typeof(Window1));
public static readonly RoutedUICommand SomeOtherAction = new RoutedUICommand("Some other action", "SomeOtherAction", typeof(Window1));
public static readonly RoutedUICommand MoreDeeds = new RoutedUICommand("More deeds", "MoreDeeeds", typeof(Window1));
}
Add a namespace in the window markup, using the namespace that the Window1 class is in:
xmlns:w="clr-namespace:NameSpaceOfTheApplication"
Now I can create bindings for the commands just as for the application commands:
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Open" Executed="CommandBinding_Open" />
<CommandBinding Command="ApplicationCommands.Paste" Executed="CommandBinding_Paste" />
<CommandBinding Command="w:Command.DoSomething" Executed="CommandBinding_DoSomething" />
<CommandBinding Command="w:Command.SomeOtherAction" Executed="CommandBinding_SomeOtherAction" />
<CommandBinding Command="w:Command.MoreDeeds" Executed="CommandBinding_MoreDeeds" />
</Window.CommandBindings>
And use the bindings in a menu for example:
<MenuItem Name="Menu_DoSomething" Header="Do Something" Command="w:Command.DoSomething" />
6 Comments
Command.DoSomething) have to be public, otherwise you will receive the following exception "CommandConverter cannot convert from System.String". I'm assuming this is because the code that is managing commands is probably in a different assembly, and as a result can't see the internal property. I just started learning WPF last week :DCommand class did you mean typeof(Command) instead of typeof(Window1)Instead of defining them in a static class, you might as well declare the commands directly in XAML. Example (adapted from Guffas nice example):
<Window.Resources>
<RoutedUICommand x:Key="DoSomethingCommand" Text="Do Something" />
<RoutedUICommand x:Key="DoSomethingElseCommand" Text="Do Something Else" />
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource DoSomethingCommand}" Executed="CommandBinding_DoSomething" />
<CommandBinding Command="{StaticResource DoSomethingElseCommand}" Executed="CommandBinding_DoSomethingElse" />
</Window.CommandBindings>
...
<MenuItem Name="Menu_DoSomething" Header="Do Something" Command="{StaticResource DoSomethingCommand}" />
5 Comments
CommandBinding_DoSomething and CommandBinding_DoSomethingElse are C# code. 3./4. For a general discussion about the advantages of RoutedCommands vs. regular Button_Click-bindings, see, for example, joshsmithonwpf.wordpress.com/2008/03/18/… (Section "Who Cares?").I Know that my answer is too late, but i hope it will help for the future.
I Like Guffa and Heinzi answers, but you can use only one command to achieve the previous result. I usually use the Help command
<Window.CommandBindings>
<CommandBinding Command="{StaticResource Help}" Executed="HelpExecuted" />
</Window.CommandBindings>
and I use CommandParametr with each call e.g
<Window.InputBindings>
<KeyBinding Command="{StaticResource Help}" Key="A" Modifiers="Ctrl" CommandParameter="Case1"/>
<KeyBinding Command="{StaticResource Help}" Key="B" Modifiers="Ctrl" CommandParameter="Case2"/>
<KeyBinding Command="{StaticResource Help}" Key="C" Modifiers="Ctrl" CommandParameter="Case3"/>
<KeyBinding Command="{StaticResource Help}" Key="D" Modifiers="Ctrl" CommandParameter="Case4"/>
<MouseBinding Command="{StaticResource Help}" MouseAction="LeftDoubleClick" CommandParameter="Case5" />
</Window.InputBindings>
or
<Button Command="Help" CommandParameter="Case6" Content="Button">
<Button.InputBindings>
<KeyBinding Command="{StaticResource Help}" Gesture="Ctrl+D" CommandParameter="Case7"/>
</Button.InputBindings>
</Button>
and in the cs file
private void HelpExecuted(object sender, ExecutedRoutedEventArgs e)
{
string str = e.Parameter as string;
switch (str)
{
case null://F1 Pressed default Help
//Code
break;
case "Case1":
//Code
break;
case "Case2":
//Code
break;
case "Case3":
//Code
break;
case "Case4":
break;
case "Case5":
//Code
break;
case "Case6":
//Code
break;
case "Case7":
//Code
break;
}
e.Handled = true;
}
and if you are using MVVM pattern
private void HelpExecuted(object sender, ExecutedRoutedEventArgs e)
{
string str = e.Parameter as string;
Mvvm_Variable.Action(Input: str);
e.Handled = true;
}
and move the switch to ViewModule site. and Action is a method in the same ViewModule class.
5 Comments
RoutedUICommand in their answers. This class has a Text property, from which text is taken to automatically populate menu entries which invoke that command (and can be used elsewhere - I bind button text to it quite often through a shared template). If you use one command (say, "Help"), all the menu items will have the same single piece of text defined in Help.Text. Depending on your preferred architecture, this may not be a big problem, but I think it's something to be aware of.