KeyDown Event on a C# WPF Window Not Working
Asked Answered
M

3

9

I'm trying to receive key strokes in a Window (Not a Form). I receive event, until a button is pressed. After that no matter what I do, the key down event doesn't fire anymore. Is there any solution? I have searched for it, seems like every one is suggesting a solution using

this.KeyPreview = true;

but this can't work here, as Window doesn't have such an attribute. Helps much appreciated. I have already set all the children Focusable to False, and Window is set to be focusable. But this hasn't helped.

The XAML is

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="MainWindow" Height="463" Width="726" AllowsTransparency="False" PreviewKeyDown="Window_PreviewKeyDown" KeyDown="Window_KeyDown_1" WindowStartupLocation="CenterScreen"  Focusable="True">
    <Window.Background>
        <RadialGradientBrush>
            <GradientStop Color="#FF3EB5FF" Offset="1" />
            <GradientStop Color="White" Offset="0" />
        </RadialGradientBrush>
    </Window.Background>
    <Grid Name="grid1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="434*" />
            <ColumnDefinition Width="270*" />
        </Grid.ColumnDefinitions>
        <Grid Margin="10,10,0,12" Name="EquiGrid"  Focusable="False">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="2*" />
                <ColumnDefinition Width="198*" />
            </Grid.ColumnDefinitions>
            <Image Grid.ColumnSpan="2" Name="EquiImage" Stretch="Uniform" Margin="0,0,0,6" />
            <Grid Grid.Column="1" Height="100" HorizontalAlignment="Left" Margin="489,90,0,0" Name="grid2" VerticalAlignment="Top" Width="200" />
        </Grid>
        <Label Content="Label" Height="28" Margin="14,12,12,0" Name="longLabel" VerticalAlignment="Top" Grid.Column="1" OpacityMask="White" BorderBrush="Red" Focusable="False">
            <Label.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="White" Offset="0.025" />
                    <GradientStop Color="#FFDBDBDB" Offset="1" />
                </LinearGradientBrush>
            </Label.Background>
        </Label>
        <Label Content="Label" Height="28" Margin="14,46,12,0" Name="latLabel" VerticalAlignment="Top" Grid.Column="1" Focusable="False">
            <Label.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="White" Offset="0.025" />
                    <GradientStop Color="#FFDBDBDB" Offset="1" />
                </LinearGradientBrush>
            </Label.Background>
        </Label>
        <TextBlock Margin="14,80,12,54" Name="descriptionText" Padding="10" Text="" Grid.Column="1" Focusable="False"><TextBlock.Background><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"><GradientStop Color="White" Offset="0.025" /><GradientStop Color="#FFDBDBDB" Offset="1" /></LinearGradientBrush></TextBlock.Background></TextBlock>
        <Button Content="Load Image" Grid.Column="1" Margin="14,0,0,12" Name="button1" Height="36" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="124" Click="button1_Click" Focusable="False" />
        <Button Content="Load XML" Grid.Column="1" Margin="0,0,12,12" Name="button2" Height="36" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="114" Click="button2_Click" Focusable="False" />
    </Grid>
</Window>

and the handler:

 private void Window_KeyDown_1(object sender, System.Windows.Input.KeyEventArgs e)
 { 
       Console.WriteLine("k"); 
 }

I have also found out that the problem is in the focus. The children, although set to be not focusable, steal the focus on the window and stop the event firing.

Monumental answered 3/4, 2012 at 10:11 Comment(6)
u mean key strokes outside your application?Paiz
No, inside it. It seems to be a pretty easy thing to do! But doesn't work.Monumental
ok, can you put some code? and which key is it?Paiz
I want to get arrow keys. As it hasn't worked yet, the code related to it is not that much, other part of the program are irrelevant. I have set the event handler in the XAML, and its code is something like thisMonumental
Don't post the code in comments. Please edit your question and at least put the relevant XAML and code-behind in there so we can get a better feel for it.Whereunto
Using your code, the event fires even after I've clicked on the buttons (if I read this correctly, your problem is that it never goes into the keydown handler after you've clicked on any of the buttons). I just put a breakpoint there and it fires every time. I had to remove the button_click and mouse movement handles to compile. What do you have in those?Whereunto
A
3

Try using the KeyDown event.

In codebehind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("KeyDown");
        System.Diagnostics.Debug.WriteLine(e.Key);
    }

    private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("PreviewKeyDown");
        System.Diagnostics.Debug.WriteLine(e.Key);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Button clicked");
    }
}

XAML

<Window x:Class="WpfApplication1.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" KeyDown="Window_KeyDown" PreviewKeyDown="Window_PreviewKeyDown">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0"></TextBox>
        <Button Grid.Row="1" Content="Click me!" Click="Button_Click"></Button>
    </Grid>
</Window>
Adriatic answered 3/4, 2012 at 11:9 Comment(10)
Thanks man, but if you look at my comments, it is exactly what I have done.Monumental
I've noticed. You forget to mention the use of arrow keys.Adriatic
Have done this. didn't help at all. I don't know the difference between this two events honestly, but I did put different things to be printed in each of the event handlers. In my tests, either both events were fired, or none.Monumental
Try starting a new WPF application and use a blank form with these eventhandlers. This code works fine, it must be something else.Adriatic
I agree with rdkleine - this works here too, so there has to be something else you're doing (probably in those "click" handlers) that somehow "affect the event".Whereunto
Did you test after clicking on the buttons?Monumental
very similar thing here: link. Someone says: The code above will work with a blank form and a form with certain controls, for example putting a single button on the form will prevent the event from firing if it has focus, there is very little you can do about this.Monumental
Nonsense, created a new project and it works fine. With focus on textbox and button after clicking button etcAdriatic
Maybe you should remove all Focusable="False"?Adriatic
It doesn't work with Focusable="False", so it's no nonesense. Setting everything to Focusable="False" could do the trick, but that's definatly not a good solution... It's a hack for if there is nothing else to do, since it's not maintainable, and maybe I do not want my Grid to be focusable...Iphagenia
B
1

You need to implement global events in WPF. This works no matter what control is currently in focus or selected.

https://blog.magnusmontin.net/2015/03/31/implementing-global-hot-keys-in-wpf/

Butcherbird answered 6/8, 2023 at 21:25 Comment(0)
I
1

Because I encountered a similar issue, I contribute by sharing my solution.

Author said : "I have also found out that the problem is in the focus". And it's also what I discovered wen I removed the Maximized property to my Window ; my content was undersized and it was more obvious to watch the reaction to Up/Down/Left/Right KeyDown event : the content inside my scrollviewer was moving.

So in my situation a simple Focusable=false on Scrollviewer resolved it.

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Focusable="False"
      MouseDown="ScrollViewer_MouseDown" MouseUp="ScrollViewer_MouseUp" MouseMove="ScrollViewer_MouseMove">
    <!-- A very interesting content -->
</ScrollViewer>

It was a loss of time because the KeyDown event is handled by default and even when it is not necessary so it wasn't possible to watch any effect. Changing the uses cases of my window was the path to my solution. I hope it can helps.

Instrumental answered 2/7 at 16:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.