I am trying to add a keyboard shortcut to the menu item in my xaml code using
<MenuItem x:Name="Options" Header="_Options" InputGestureText="Ctrl+O" Click="Options_Click"/>
with Ctrl+O
But it is not working - it is not calling the Click option.
Are there any solutions for this?
InputGestureText is just a text. It does not bind key to MenuItem.
This property does not associate the input gesture with the menu item; it simply adds text to the menu item. The application must handle the user's input to carry out the action
What you can do is create RoutedUICommand in your window with assigned input gesture
public partial class MainWindow : Window
{
public static readonly RoutedCommand OptionsCommand = new RoutedUICommand("Options", "OptionsCommand", typeof(MainWindow), new InputGestureCollection(new InputGesture[]
{
new KeyGesture(Key.O, ModifierKeys.Control)
}));
//...
}
and then in XAML bind that command to some method set that command against MenuItem. In this case both InputGestureText and Header will be pulled from RoutedUICommand so you don't need to set that against MenuItem
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:MainWindow.OptionsCommand}" Executed="Options_Click"/>
</Window.CommandBindings>
<Menu>
<!-- -->
<MenuItem Command="{x:Static local:MainWindow.OptionsCommand}"/>
</Menu>
you should succeed in this way:
Defining MenuItem Shortcuts
By using KeyBindings:
<Window.CommandBindings> <CommandBinding Command="New" Executed="CommandBinding_Executed" /> </Window.CommandBindings> <Window.InputBindings> <KeyBinding Key="N" Modifiers="Control" Command="New"/> </Window.InputBindings>
First, this is my code :
<Window ...>
<Window.Resources>
</Window.Resources>
<Window.InputBindings>
<KeyBinding Key="Space" Command="{Binding KeyboardCommand}" CommandParameter="Space"/>
<KeyBinding Key="OemPeriod" Command="{Binding KeyboardCommand}" CommandParameter="Blank"/>
<KeyBinding Key="D0" Command="{Binding KeyboardCommand}" CommandParameter="Rest"/>
<KeyBinding Key="D1" Command="{Binding KeyboardCommand}" CommandParameter="N1"/>
<KeyBinding Key="D2" Command="{Binding KeyboardCommand}" CommandParameter="N2"/>
<KeyBinding Key="D3" Command="{Binding KeyboardCommand}" CommandParameter="N3"/>
<KeyBinding Key="D4" Command="{Binding KeyboardCommand}" CommandParameter="N4"/>
<KeyBinding Key="D5" Command="{Binding KeyboardCommand}" CommandParameter="N5"/>
<KeyBinding Key="D6" Command="{Binding KeyboardCommand}" CommandParameter="N6"/>
<KeyBinding Key="D7" Command="{Binding KeyboardCommand}" CommandParameter="N7"/>
<KeyBinding Modifiers="Control" Key="Space" Command="{Binding KeyboardCommand}" CommandParameter="Space"/>
<KeyBinding Modifiers="Control" Key="OemPeriod" Command="{Binding KeyboardCommand}" CommandParameter="Blank"/>
<KeyBinding Modifiers="Control" Key="D0" Command="{Binding KeyboardCommand}" CommandParameter="Rest"/>
<KeyBinding Modifiers="Control" Key="D1" Command="{Binding KeyboardCommand}" CommandParameter="N1"/>
<KeyBinding Modifiers="Control" Key="D2" Command="{Binding KeyboardCommand}" CommandParameter="N2"/>
<KeyBinding Modifiers="Control" Key="D3" Command="{Binding KeyboardCommand}" CommandParameter="N3"/>
<KeyBinding Modifiers="Control" Key="D4" Command="{Binding KeyboardCommand}" CommandParameter="N4"/>
<KeyBinding Modifiers="Control" Key="D5" Command="{Binding KeyboardCommand}" CommandParameter="N5"/>
<KeyBinding Modifiers="Control" Key="D6" Command="{Binding KeyboardCommand}" CommandParameter="N6"/>
<KeyBinding Modifiers="Control" Key="D7" Command="{Binding KeyboardCommand}" CommandParameter="N7"/>
...
</Window.InputBindings>
<Grid>
...
</Grid>
There's NO ERROR on those code, so it works just fine. But, it seems that the InputBindings can get a lot of lines if my application has a lot of InputBindings.
So, is it possible to simplify/shorten them (in any way)? It is because my application will need a lot of InputBindings / KeyBinding's Modifier combination, and it feel input it one-by-one will look "not neat". M
Or maybe it is the only way to do (with MVVM)?
Please clarify anything needed :D
Just in case needed, these are the related methods in Command and ViewModel class :
public void Execute(object parameter)
{
Notes note;
if (Enum.TryParse(parameter.ToString(), out note))
{
_vm.AddOrUpdateNote(note, Keyboard.Modifiers);
}
else
{
...
}
}
A part of my ViewModel :
public void AddOrUpdateNote(Notes note, ModifierKeys mKeys)
{
if (mKeys == ModifierKeys.Control)
{
...
}
else if (mKeys == ModifierKeys.Shift)
{
...
}
else
{
...
}
}
So, there's a minor behavior difference depending which Modifier Key is pressed. (Splitting into different methods feels awful for me)
UPDATE :
I've read some explanations on InputGestures. In http://msdn.microsoft.com/en-us/library/ms752308%28v=vs.110%29.aspx it's said this.InputBindings.Add(Blabla) (from xaml.cs i guess), can it be done in the ViewModel? Or is it strictly need to be done via XAML, so, if I have a lot of key combination in my application such in the example above, it still need to be done that "long" way?
Please provide some code samples if possible, so I can understand it better. Thanks
(Not quite sure too how to ask it, so please feel free to clarify)
If your sole objective is to cut down on the number of manual KeyBindings, you can do something like this:
var keys = new List<Key> { Key.Space, Key.OemPeriod, Key.D1, [...]};
foreach(var key in keys)
{
this.InputBindings.Add(new KeyBinding() { Command = MyCommandClass.KeyboardCommand, CommandParameter = key});
]
But I don't like this approach, as it requires you to implement delegation of your command yourself rather than having WPF do it. You will need to switch on the CommandParameter and modifierkey.
The above will absolutely work, but having a single command do all the work seems counterintuitive to me. I would implement several commands (like AddNoteCommand) so that they can each hold their own Execute and CanExecute method.
Yes, you'd have a few extra lines of code per Command, but your command implementation would not have to know HOW you accessed the command. Imagine you want to add these commands as MenuItems, or Buttons in your UI.
There might be something I'm missing (I don't know what the commands do), but I can't really imagine a scenario where I would choose this approach.
That doesn't necessarily make it wrong though ;)
There's actually a trick you can use around attached properties. The syntax for applying an attached property is really just 'syntactical sugar' to call a static function on a particular class from XAML. Knowing that, you can build up a 'Utility' class that has a bunch of methods you can call from XAML using the attached property syntax.
As such, you could do something like this...
public namespace My{
public static class Util {
[AttachedPropertyBrowsableForType(typeof(KeyBinding))]
public static void SetSet(KeyBinding keyBinding, string bindingData){
// Add code here to parse the string and do with it what you will.
// For instance, you can split it on a pipe character to get the modifier,
// parameter and key, then just apply it to the passed-in keyBinding here.
// I'll leave this part as an exercise for you to research.
}
}
}
and you can use it like this...
<Window ...>
<Window.InputBindings>
<KeyBinding my:Util.Set="Control|D1|N1" />
<KeyBinding my:Util.Set="Control|D2|N2" />
<KeyBinding my:Util.Set="Control|D3|N3" />
...
</Window.InputBindings>
</Window>
Notes:
The method name to support attached properties is a static method named Set[PropertyName] on an 'owning' class. When you use it in XAML, it looks like OwningClass.PropertyName="bla". In my example, by calling the class Util and the static method SetSet the 'property name' becomes Set and thus in XAML (where 'my' is the imported xmlns value), it looks like my:Util.Set="bla" which reads more clearly as to my intent.
I prefer the data type string so you can pass in a ton of info in one value, then just parse it as you see fit. But you can use any data type you want. For instance, you could take a CommandInfo class that exposes your Modifiers, Key and Parameter properties, then create a MarkupExtension to 'create' that class and which takes them in as constructor parameters, then set it via the attached property syntax, like so:
<InputBinding my:Util.Set="{my:CommandInfo Control, D1, N1}" ... />
This attached property syntax has proven pretty amazing in simplifying our XAML. As an example, I use these techniques to more easily configure my grid layouts. For instance, instead of this...
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="1", Grid.ColumnSpan="2" />
</Grid>
I can now just do this...
<Grid is:GridUtil.Layout="Auto,Auto,Auto|Auto,*">
<TextBlock is:GridUtil.Cell="1,1s2" />
</Grid>
Notes:
Layout is a comma-separated list of row heights, a pipe character, then comma-separated list of column widths
Cell is a row (and possibly row-span with 'sN'), a comma, then a column (and possibly column-span with 'sN')
Hope this helps!
Within my window (let's say MyCanvas) there's a new command definition which I then bind to my window. Usually the handlers for CanExecute and Executed are directly within MyCanvas. But is it somehow possible to bind the CanExecute and Executed handlers to a relative path like for example MyCanvas.Logic.CanExecute_OpenCamera?
This is my current XAML.
<Window.Resources>
<RoutedUICommand x:Key="OpenCamera" Text="Open camera" />
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource OpenCamera}" CanExecute="CanExecute_OpenCamera" Executed="Executed_OpenCamera"/>
</Window.CommandBindings>
This is what I'm trying to define. Logic is public property of MyCanvas.
<Window.Resources>
<RoutedUICommand x:Key="OpenCamera" Text="Open camera" />
</Window.Resources>
<Window.CommandBindings>
<CommandBinding Command="{StaticResource OpenCamera}" CanExecute="Logic.CanExecute_OpenCamera" Executed="Logic.Executed_OpenCamera"/>
</Window.CommandBindings>
You can, but you have to use converters which create delegates to the respective methods from a bound object of the class, or from its type, if the methods are static. See http://wpfglue.wordpress.com/2012/05/07/commanding-binding-controls-to-methods/ for details.
I am working with WPF. I want to create keyboard shortcuts for my WPF application. I have created as following. The first command binding tag for "open" is working and command binding for exit is not working. I dont know what is the reason.
<Window.CommandBindings>
<CommandBinding Command="Open" Executed="CommandBinding_Executed"/>
<CommandBinding Command="Exit" Executed="CommandBinding_Executed_1" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Command="Open" Key="O" Modifiers="control" />
<KeyBinding Command="Exit" Key="E" Modifiers="control"/>
</Window.InputBindings>
Above code is getting the following error:
Cannot convert string 'Exit' in attribute 'Command' to object of type
'System.Windows.Input.ICommand'. CommandConverter cannot convert from
System.String. Error at object 'System.Windows.Input.CommandBinding' in
markup file 'WpfApplication2;component/window1.xaml' Line 80 Position 25.
You problem is that there is no exit command. You'll have to roll your own.
See here for built-in ApplicationCommands
It's pretty easy to create your own, I use a static utility class to hold common commands that I use often. Something like this:
public static class AppCommands
{
private static RoutedUICommand exitCommand = new RoutedUICommand("Exit","Exit", typeof(AppCommands));
public static RoutedCommand ExitCommand
{
get { return exitCommand; }
}
static AppCommands()
{
CommandBinding exitBinding = new CommandBinding(exitCommand);
CommandManager.RegisterClassCommandBinding(typeof(AppCommands), exitBinding);
}
}
Then you should be able to bind it like this:
<KeyBinding Command="{x:Static local:AppCommands.Exit}" Key="E" Modifiers="control"/>
In my XAML I have this:
<UserControl.CommandBindings>
<CommandBinding Command="Help"
CanExecute="HelpCanExecute"
Executed="HelpExecuted" />
</UserControl.CommandBindings>
<MenuItem Header="Help" Command="Help" />
This works fine. So when I click the context menu, HelpExecuted() gets called.
Now I want to do the same again except use a custom command instead of the Help command. So what I do is:
public RoutedCommand MyCustomCommand = new RoutedCommand();
and change my XAML to:
<UserControl.CommandBindings>
<CommandBinding Command="MyCustomCommand"
CanExecute="HelpCanExecute"
Executed="HelpExecuted" />
</UserControl.CommandBindings>
<MenuItem Header="Help" Command="MyCustomCommand" />
But i get the error: Cannot convert string 'MyCustomCommand' in attribute 'Command' to object of type 'System.Windows.Input.ICommand'. CommandConverter cannot convert from System.String.
What am I missing here? And please note that I want to do it all in XAML, i.e. don't want to use CommandBindings.Add(new CommandBinding(MyCustomCommand....
Oops, sorry, was a bit fast to post my original answer. I now see that the problem is not with the type but with the CommandBinding. You need to use a markup extension to resolve the command name. I usually make my commands static in their declaration like this:
namespace MyApp.Commands
{
public class MyApplicationCommands
{
public static RoutedUICommand MyCustomCommand
= new RoutedUICommand("My custom command",
"MyCustomCommand",
typeof(MyApplicationCommands));
}
}
And in the XAML:
<UserControl x:Class="..."
...
xmlns:commands="clr-namespace:MyApp.Commands">
...
<UserControl.CommandBindings>
<CommandBinding Command="{x:Static commands:MyApplicationCommands.MyCustomCommand}"
CanExecute="HelpCanExecute"
Executed="HelpExecuted" />
</UserControl.CommandBindings>
You need to bring in the namespace of the containing class by using xmlns. I called it 'commands' in my example above.
Original post below:
Try changing the type of the command to RoutedUICommand. The constructor is a bit different:
public RoutedUICommand MyCustomCommand
= new RoutedUICommand("Description", "Name", typeof(ContainingClass));