views:

45

answers:

2

I have a button on a XAML form that calls the btnName_Click() code in the backing cs file.

I also want to assign a keyboard shortcut to run that same code. Basically CTRL<- or something similar.

This needs to work regardless of the control I'm currently in (there's a TextBox for example that I want to ensure doesn't capture the event if I'm in there).

I've read up on routed commands but that seems like a lot of work for something which should be simple.

Is there an easy way to do this or do I need to create routed commands? If I do need to use them, what's the simplest way to achieve what I want?

+2  A: 

In the root Window element hook into the KeyDown event:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        Keyboard.KeyDown="Window_KeyDown"
        >

Code behind:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        this.DoSomething();
    }

    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Right && e.KeyboardDevice.Modifiers == ModifierKeys.Control)
        {
            this.DoSomething();
        }
    }

    private void DoSomething()
    {
        MessageBox.Show("Whatever");
    }

On a side note, I would suggest looking into the M-V-VM approach, and more specifically Commands and Attached behaviors. That would make this much more unit testable.

BFree
+1 for the command recommendation. Sometimes it can be a hard sell but it's really the right way of doing this.
Josh Einstein
+1  A: 

Have your XAML as

<StackPanel PreviewKeyDown="StackPanel_PreviewKeyDown">
    <Button x:Name="btnName" Click="btnName_Click" Height="Auto" Width="Auto" Content="Name"></Button>
    <TextBox x:Name="tb"></TextBox>
</StackPanel>

and your cs as

public MainWindow()
{
    InitializeComponent();
}

private void btnName_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("This is from btnName");
}

private void StackPanel_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Left)
    {
        btnName_Click(sender, new RoutedEventArgs());
        e.Handled = true;
    }
}

You should put the PreviewKeydown event on the topmost control like your window so that once Ctrl <- is hit only the window or top control handles it and no one else.

PreviewKeyDown is a tunneled event - it originates at the topmost control and goes down to actual control.

Nitin Chaudhari
Thanks, Nitin, that showed how to call the button click directly and gave me the control over the keystroke to stop it from hitting the textbox. I didn't need a StackPanel, I just put it straight onto the top-level Window. But other than that minor change, it all worked perfectly.
paxdiablo