Cosas mías

May 19, 2006

Las cosas del NET (o cómo controlar las teclas en un DataGrid)

Filed under: Programación

Esta mañana mi amigo Peni y yo hemos entablado un sesudo diálogo sobre el tema del título. La idea básica consiste en controlar todas las pulsaciones de teclas cuando un usuario trabaje dentro de un DataGrid. Lo que en un principio iba a ser una cosa sencilla se ha convertido en un buen jaleo y bastantes mensajes cruzados entre los dos.

La primera idea fue la de capturar el evento KeyPress del grid y actuar en consecuencia. Pues no funciona, o funciona sólo cuando no haya ninguna celda en él. Vale. Pues entonces controlemos el KeyPress de las celdas, pero resulta que no existe tal evento para ellas. Bien empezamos. Si un control Text lo tiene, ¿como es que un control Text dentro del grid no? Misterios del .NET Framework, de Microsoft y de sus by design, pero lo cierto es que dicho evento debería estar disponible.

Otra opción es la de comprobar si el grid tiene la posibilidad de activar un modo KeyPreview igual que tienen las fichas. Pues no, no lo tiene. Desde mi punto de vista, y seguro que desde el de Peni, es una jodida limitación bastante evidente.

Como se dijo en cierta película del siglo anterior, “siempre nos quedará París” o, lo que es lo mismo, “utilicemos el KeyPress y el KeyPreview de la ficha”, que para algo están. Asignando true a KeyPreview en una ficha, todas las pulsaciones de tecla pasan por ella antes de ser reenviadas al control correspondiente, siempre y cuando nosotros así lo queramos.

Capturamos el evento KeyPress de la ficha, evento que se disparará para todas y cada una de las teclas que se pulsen dentro de ella. En dicho evento recibimos un objeto del tipo Object llamado sender y una referencia a un objeto de la clase KeyPressEventArgs. Si asignamos true a la propiedad Handled de esta clase, la tecla se perderá para el control que estuviera destinada (otra cosa es que funcione, que no lo hace para la mayoría de los controles hijo, pasándose por el forro de donde ya sabemos la funcionalidad).

El objeto sender es el que nos interesa, pues es una instancia polimórfica del control que genera el envento, en nuestro caso, presuntamente y hasta que no se demuestre lo contrario, nuestro control grid. O eso se deja entrever en la documentación. Sólo nos queda promover dicho objeto a su clase exacta, previa comprobación de que se trata del grid y no de otro control cualquiera presente en la ficha. Para ello utilizamos un código parecido a este:

Type tipo=sender.GetType();
if(tipo.ToString()=="DataGrid") //Así no funciona, pero para efectos de demo nos vale
...

¿Qué suponemos que valdrá tipo.ToString()? Aquí es donde la presuntez pierde su valor y se convierte en certeza… ¡Vale “Form1″, que es el nombre de la ficha! Esto me lleva a preguntarme: ¿Para qué cojones sirve entonces el objeto sender? Evidentemente se trata de un absurdo más, porque ya sabemos que estamos en la ficha. En otras herramientas RAD, no voy a decir el nombre, sender vale lo que tiene que valer.

En fin, otro by design más.

Pero aquí no acaba la cosa, “aún hay más”, que diría cierto ratón volador sin alas. Vamos a por la tercera. ¿No dicen que a la tercera? Veremos. Nos queda una última técnica, la de comprobar en el evento quién tiene el foco, y si se trata del grid, lo tenemos hecho. Presuntamente hecho, porque el foco no lo tiene el grid, sino el control de edición que está dentro del grid. Para verlo deberíamos recorrer todos los subcontroles del mismo, comprobar mediante reflexión si tienen la propiedad Focused y luego consultarla. Eso o meter el código dentro de un try/catch y jugar a ver lo rápido que va… No se rían, por favor, eso de picar una tecla cada cuarto de hora es lo habitual.

Descartada esta opción, nos vamos a por la cuarta, que vamos a adelantar, funciona, es sencilla, evidente por sí misma y carente de cafeína, destrozos de teclado y gritos de frustación… Si el grid está en modo de edición, por cojones ha de tener el foco, así que, en vb, nuestra duda/problema queda, felizmente y tras casi una mañana de peleas, resuelta:

Private Sub Form1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress
If DataGridView1.IsCurrentCellInEditMode Then
MsgBox(e.KeyChar.ToString)
End If
End Sub

Gracias por leernos y no olviden mineralizarse y supervitaminarse.

7 Comments »

The URI to TrackBack this entry is: http://rfog.blogsome.com/2006/05/19/las-cosas-del-net-o-como-controlar-las-teclas-en-un-datagrid/trackback/

  1. No cabe duda que escribes bien. Hasta me pareció entretenido, con lo que nos hizo ’sufrir’!!! Además leido asi, parece sencillo y todo ;-) Teniendo en cuenta que llevo apenas una semana con el .NET … empezamos bien … buf, la que me espera. Aunque siempre es bueno tenerte a mano para darte la paliza ;-) A este paso yo aprendo C++ y tu VB :-P

    Comment by Peni — May 19, 2006 @ 6:59 pm

  2. Je je. No me preocupo mucho por el estilo, la verdad sea dicha, y no suelo corregir más que en una segunda lectura rápida tras la escritura… Podría darle un tono más reposado, alargando los momentos cruciales, pero la verdad es que me interesa lo que cuento, no cómo lo cuento…

    A este paso yo aprendo C++ y tu VB

    Nooooooooooooooooooooooooooooooooooooooooooooooooooooo.
    ¡¡Vade retro!! :-P

    Comment by rfog — May 19, 2006 @ 7:17 pm

  3. Viendo lo que se puede hacer con .NET entiendo el entusiasmo de los programadores de C+ al ser un lenguaje orientado a objetos ‘de verdad’, pero estando en .NET las diferencias se difuminan bastante. Los objetos, metodos, propiedades, ***bugs*** … son los mismos en C y VB y además me llevé la agradable sorpresa de que el código de VB6 no es tan dificil de adaptar a VB .NET, pero eso si, que a nadie se le ocurra intentar migrar un proyecto en curso. .NET es para empezar de cero, con la ventaja de poder adaptar las rutinas que uno esta acostumbrado a manejar. Incluso el acceso a datos se puede hacer como en VB6, pero perdiendo toda la potencia de los objetos de .NET

    Comment by Peni — May 19, 2006 @ 7:30 pm

  4. Muchas gracias…. No sabes el Alivio que me causa no tener que hacer esa otra respuesta que dan por ahi de crear un control con herencia y en otro clase y Uff que tantas otras cosas.. Todo Funciona perfecto pero no es capas de captar la tecla enter para poder Cambiarla por TAB en el datagrid.. esto de verdad que me esta quitando el Sueño y me niego a crear otra clase! seran tarados!!! estos tios de Microsoft?

    Comment by Francisco de la Fuente — October 25, 2006 @ 5:46 pm

  5. Je, je.

    Hay ciertas decisiones de diseño del .NET bastante desafortunadas, parece mentira que vengan de la misma cabeza que creó la VCL de Borland.

    Hablando sinceramente, no son desafortunadas, son risibles.

    Comment by rfog — October 25, 2006 @ 6:47 pm

  6. Excelente my partner, te juro que estuve dos dias intentando eso del (Enter) dentro del datagrid, y lo que estas dando a conocer es sumamente valioso para mi. Me has evitado, al igual, que a otros, crear una clase heredada mas. Muchas gracias por tu aporte!!

    Comment by Gustavo — April 8, 2008 @ 12:05 am

  7. rayos!
    no me funciona!!!

    Comment by litaPau — October 6, 2009 @ 7:14 pm

RSS feed for comments on this post.

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>



Anti-spam measure: please retype the above text into the box provided.

Get free blog up and running in minutes with Blogsome
Theme designed by Gary Rogers