1

I'm trying to create a UserControl that displays a multi-page image and allows the user to zoom, rotate, and browse an image. The one part I'm having a problem with is getting the keyboard shortcuts setup properly. I figured out I need to have the InputBindings setup on the Window class that is hosting the UserControl. I did figure out how to create an InputBinding in the code behind but I'm expecting a lot of keyboard shortcuts and I think having them in the XAML will be easier. Here is an example project that I'm testing this out in:

MainWindow.xaml

<Window x:Class="CommandTest.Window1"  
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
xmlns:local="clr-namespace:CommandTest"  
Title="Window1" Height="300" Width="344">
<Window.InputBindings>
    <KeyBinding
        Key="N"
        CommandTarget="x:UCon"
        />
</Window.InputBindings>

<StackPanel>
    <local:NestedControl x:Name="UCon">
    </local:NestedControl>
</StackPanel>
</Window>  

MainWindow.Xaml.cs

using System.Windows;
using System.Windows.Input;

namespace CommandTest
{
    public partial class Window1 : Window
    {
         public Window1()
         {
             InitializeComponent();
             KeyGesture keyg = new KeyGesture(Key.OemPlus, ModifierKeys.Control);

             KeyBinding kb = new KeyBinding((ICommand)UCon.Resources["Commands.ZoomOut"], keyg);

             kb.CommandTarget = UCon;

             this.InputBindings.Add(kb);   
         }

     }
}

UserControl1.xaml

<UserControl x:Class="CommandTest.NestedControl"  
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <UserControl.Resources>
        <!-- UI commands. -->        
        <RoutedCommand x:Key="Commands.ZoomOut" />        
    </UserControl.Resources>

    <UserControl.CommandBindings>
        <CommandBinding x:Name="ZoomCommand" Command="{StaticResource Commands.ZoomOut}" CanExecute="ZoomCommand_CanExecute" Executed="ZoomCommand_Executed"/>        
    </UserControl.CommandBindings>
    <Button Command="{StaticResource Commands.ZoomOut}">Zoom</Button>
</UserControl>  

UserControl1.xaml.cs

using System.Windows.Controls;
using System.Windows.Input;

namespace CommandTest
{
    public partial class NestedControl : UserControl
    {
        public NestedControl()
        {
            InitializeComponent();
        }

        private void ZoomCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void ZoomCommand_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            System.Windows.MessageBox.Show("Zoom", "Zoom");
        }        
    }
}
Gariig
  • 131
  • 1
  • 8

1 Answers1

0

Instead of binding the key to the Window, bind it to the command itself (You could do this in the constructor for ZoomCommand if this is a custom command):

ZoomCommand.InputGestures.Add(new KeyGesture(Key.N));

Then, in the Constructor for the UserControl:

Window.GetWindow(this).CommandBindings.Add(new CommandBinding(new ZoomCommand(), ZommCommand_handler));
Greg Sansom
  • 20,442
  • 6
  • 58
  • 76
  • Is creating the command in code a better avenue than creating the command in XAML? Also does that mean you can't add the InputBinding to the host of the UserControl in XAML? Also, this solution doesn't work. The UserControl1 doesn't have KeyboardFocus so the InputBinding never fires. If you click on the button and then use the KeyGesture the MessageBox will show – Gariig Nov 12 '10 at 14:26
  • Whether you use code or XAML to create the commands is really up to you - neither is "better". I chose code here because it requires fewer lines so might be a bit easier to understand. I have edited my answer to bind the command to the window instead. – Greg Sansom Nov 14 '10 at 22:55