wpf - detectar - on key pressed c#
¿Cómo puedo capturar el evento KeyDown en un objeto WPF Page o UserControl? (8)
Tengo una página con un UserControl en ella. Si el usuario presiona Esc en cualquier parte de la página que quiero manejar.
Pensé que esto sería tan fácil como conectar el evento PreviewKeyDown, probar la tecla Esc y luego manejarlo. Sin embargo, cuando coloqué el punto de interrupción en el controlador de eventos, descubrí que nunca me llamaron. Pensé que tal vez el UserControl podría ser golpeado, así que probé PreviewKeyDown allí ... el mismo resultado.
¿Alguien sabe el lugar adecuado para probar KeyDown o PreviewKeyDown en un objeto de página?
Adjuntar al evento de la ventana
Después de cargar el control, conéctelo al evento KeyDown
la ventana (o cualquier evento) usando Window.GetWindow(this)
, de Window.GetWindow(this)
forma:
El XAML
<UserControl Loaded="UserControl_Loaded">
</UserControl>
El código detrás
private void UserControl_Loaded(object sender, RoutedEventArgs e) {
var window = Window.GetWindow(this);
window.KeyDown += HandleKeyPress;
}
private void HandleKeyPress(object sender, KeyEventArgs e) {
//Do work
}
¿Qué funcionó exactamente para mí?
Solo en el evento de ventana cargada escucha el evento PreviewKeyDown:
void GameScreen_Loaded(object sender, RoutedEventArgs e)
{
this.PreviewKeyDown += GameScreen_PreviewKeyDown;
this.Focusable = true;
this.Focus();
}
void GameScreen_PreviewKeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("it works!");
}
Creo que el evento PreviewKeyDown es un evento enrutado túnel, en lugar de un burbujeo. Si ese es el caso, entonces si su página no está recibiendo el evento, el UserControl tampoco debería estar porque está debajo de la página en el árbol visual. Tal vez intente manejarlo en el nivel superior de su aplicación (¿Ventana quizás?) Y vea si está recibiendo el evento.
Otra opción que podría ayudar sería usar algo como Snoop en CodePlex para descubrir a dónde van los eventos.
Establecer la propiedad enfocable en verdadero en mi UserControl resolvió el problema para mí.
Esto se prueba y definitivamente funciona.
Private Sub textbox1_PreviewKeyDown(sender As Object, e As KeyEventArgs) Handles textbox1_input.PreviewKeyDown
If (e.Key = Key.Down) Then
MessageBox.Show("It works.")
End If
End Sub
''detect key state directly with something like this below
Dim x As KeyStates = System.Windows.Input.Keyboard.GetKeyStates(Key.Down)
PreviewKeyDown es lo que la mayoría de la gente extraña. Piense en PreviewKeyDown como un observador general de eventos de teclado, (pero no puede afectarlos si no estoy equivocado) y se están escuchando los evens de KeyDown dentro de los límites del control o la clase en la que se encuentra actualmente.
He tenido el mismo problema. Tengo una ventana que alberga un Marco que carga / navega a varias Páginas que a su vez contienen solo 1 Control de Usuario que contiene Controles / Elementos normales (Etiquetas, Hipervínculos, etc.).
¡lo que descubrí (después de algunas horas de frustración, por supuesto!) es que si NO se enfoca en uno de los Controles / Elementos mencionados anteriormente, el evento PreviewKeyDown NO se activa en el UserControl (se detiene en algún lugar en el nivel Frame) pero tan pronto como pones el foco (por ejemplo, llamando a ctrl.Focus () dentro del controlador de eventos Loaded de UserCotrol) en uno de los controles ocurre magia, funciona, el evento se dispara también para el UserControl.
por supuesto, pensar en esto luego tiene suficiente sentido, pero estoy 100% seguro de que esto sorprenderá al menos a 5 de cada 10 personas :) una pequeña cosa loca llamada WPF ...
¡aclamaciones!
Propongo un método que fortalece el que se menciona en @Doc.
El siguiente código @Doc mencionado funcionará dado que el evento enrutado KeyDown se bordea a la Window
más externa. Una vez que Window
recibe el evento KeyDown borrado de un elemento interno, Window
activa cualquier controlador de eventos KeyDown registrado en él, como este HandleKeyPress
.
private void UserControl_Loaded(object sender, RoutedEventArgs e) {
var window = Window.GetWindow(this);
window.KeyDown += HandleKeyPress;
}
private void HandleKeyPress(object sender, KeyEventArgs e) {
//Do work
}
Pero esto +=
es arriesgado, es más probable que un programador olvide anular el registro del controlador de eventos. Luego se producirá una pérdida de memoria o algunos errores.
Aquí sugiero,
YourWindow.xaml.cs
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
// You need to have a reference to YourUserControlViewModel in the class.
YourUserControlViewModel.CallKeyDown(e);
// Or, if you don''t like ViewModel, hold your user-control in the class then
YourUserControl.CallKeyDown(e);
}
YourUserControlViewModel.cs o YourUserControl.xaml.cs
public void CallKeyDown(KeyEventArgs e) {
//Do your work
}
No es necesario codificar en xaml.
Tuve un problema similar al llamar a la ventana de WPF fuera de WinForms. Ninguno de los eventos KeyDown o PreviewKeyDown se activaron .
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.Show();
Sin embargo, al mostrar la ventana como un diálogo , funcionó
var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.ShowDialog();
El evento PreviewKeyDown se disparó como un amuleto para las teclas de Escape y Flecha .
void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Escape:
this.Close();
break;
case Key.Right:
page_forward();
break;
case Key.Left:
page_backward();
break;
}
}
Espero que esto funcione.