2009-09-22 15 views
15

En una aplicación WPF, tengo un control que he derivado de TextBox como esto:WPF: OnKeyDown() no ser llamado para tecla de espacio en el control derivado de WPF TextBox

public class SelectableTextBlock : TextBox 
{ 
    protected override void OnKeyDown(KeyEventArgs e) 
    { 
     base.OnKeyDown(e); 
     e.Handled = false; 
    } 
} 

El método OnKeyDown no es se llama cuando se ingresa un espacio en el TextBox, ni cuando se pulsa Retroceso, pero se dispara para otra entrada, incluidos los caracteres imprimibles normales (por ejemplo, 'a') y las teclas modificadoras (por ejemplo).

Estoy usando este control con IsReadOnly establecido en verdadero para que pueda mostrar texto seleccionable, no editable. El control utilizado dentro de DataGrid de WPFToolkit, y quiero que los eventos KeyDown se propaguen por la cuadrícula de datos, incluso si el SelectableTextBlock tiene foco, por lo que estoy usando un control personalizado para marcar explícitamente el evento como no controlado.

El problema es que el evento ni siquiera está bajo mi control para ciertas teclas. No puedo usar OnPreviewKeyDown en DataGrid para evitar esto, ya que quiero que otros controles utilizados en la cuadrícula de datos traguen el espacio del evento KeyDown.

¿Alguien sabe cómo puedo obtener el evento KeyDown para que la tecla de espacio se propague?

Gracias.

Respuesta

12

Parece que el problema es que el espacio (y de retroceso, etc.) evento de tecla pulsada se está manejando ya dentro del cuadro de texto, antes de que se propaga hacia arriba a mi control derivado. Supongo que como parte del proceso de composición de texto, como Wim publicó.

Para solucionar esto, he agregado un controlador que recibirá el evento de desactivación de teclas incluso si ya se ha manejado, y establece su miembro Handled en falso, para permitir que continúe burbujeando normalmente. En el ejemplo de abajo solo hace esto para las teclas de espacio, pero en mi caso necesitaré hacer esto para cualquier evento clave que realmente no quiero que se maneje en mi SelectedableTextBlock, ya que no sé qué eventos clave en los que los padres podrían estar interesados ​​todavía.

public class SelectableTextBlock : TextBox 
{ 
    public SelectableTextBlock() : base() 
    { 
     this.AddHandler(SelectableTextBlock.KeyDownEvent, new RoutedEventHandler(HandleHandledKeyDown), true); 
    } 

    public void HandleHandledKeyDown(object sender, RoutedEventArgs e) 
    { 
     KeyEventArgs ke = e as KeyEventArgs; 
     if (ke.Key == Key.Space) 
     { 
      ke.Handled = false; 
     } 
    } 
    ... 
} 

Por supuesto, estoy todavía está interesado si alguien tiene una mejor solución ...

Gracias, E.

2

Tuve este problema con espacios y eventos una vez en un cuadro de texto. ¿Los eventos NO se activan solo cuando agrega o elimina un carácter de espacio?

Esto es lo que obtuve como respuesta: (http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/446ec083-04c8-43f2-89dc-1e2521a31f6b)

Debido a que algunos IME tratarán a golpe de teclado espacios en blanco como parte del proceso de composición de texto, es por eso que se come por Avalon reportar el texto compuesta correcta a través de TextInput evento.

Podría estar completamente fuera del alcance, pero leer este hilo emmideatly me hizo pensar en ese problema que una vez tuve.

Saludos cordiales, Wim

+0

Gracias por su respuesta, Wim. Parece un problema relacionado. Descubrí que el evento no se activa para los espacios, retrocede y elimino las teclas. Mientras que en su caso usted estaba tratando de detener la pulsación de la tecla de espacio manejada por el cuadro de texto y lo hizo manejando la vista previa, estoy tratando de permitir que el evento se convierta en controles padres para que esto no funcione para mí . Tengo una solución alternativa que maneja los eventos de pulsación de tecla y los establece para que sean manejados. Publicaré el código de interés general en una respuesta a mi pregunta original. Todavía creo que debe haber una mejor manera. Gracias, E. – Ergwun

+0

Debería haber leído: "Tengo una solución alternativa que maneja los eventos de pulsación de tecla y los establece en * no administrado *." – Ergwun

2

derivar un ejemplo, RestrictKeysTextBox del cuadro de texto.

public class RestrictKeysTextBox : TextBox 
{ 
    .... 
} 

Anule el evento OnPreviewKeyDown en el RestrictKeysTextBox.

ponga la lógica de esta anulación de esta manera:

if (e.Key == Key.Space) 
{ 
    e.Handled = true; 
} 

Enlazar la instancia de la RestrictKeysTextBox a su cuadrícula de datos.

Eso debería funcionar sin anular el OnPreviewKeyDown en el DataGrid y eliminar los problemas asociados.

14

El evento PreviewKeyDown existe exactamente para este tipo de cosas.

private void spacebarHandler_PreviewKeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Key == Key.Space) 
     e.Handled = true; 
} 

Su controlador KeyDown nunca recibirá el evento KeyDown para la barra espaciadora.

+1

No funciona para mí en .NET 4.5 – Logan

+2

Me funciona en .Net 4.6.1 – Dabblernl