none
DataGridView en keypress RRS feed

  • Pregunta

  • Hola a todos, por favor si alguien me puede ayudar, con el keyprees DataGridView, cada vez que doy un enter en la celda se va a la siguiente fila, pero como hago para que se mantenga en el mismo sitio o se vaya a la otra columna de la misma fila que estoy dandole un enter y cuando doy la fecha hacia abajo recien pueda ir a la siguiente fila.

     

    Gracias de ante mano

     

    Russvell Soto

    lunes, 29 de octubre de 2007 20:09

Respuestas

  • Saludos Leonardo:

    Te pido un poco de paciencia, estoy incursionando en la programación en punto net, podrías por favor detallar un poco cual fue la solución final, he intentado copiar el último bloque de código publicado por ti pero no se exactamente donde hacerlo.

    Gracias de antemano!

    • Marcado como respuesta RJ Jesus viernes, 8 de febrero de 2013 0:51
    lunes, 7 de febrero de 2011 5:09

Todas las respuestas

  • Hola Russvell

    Te envio este codigo de ejemplo

     

    Private Sub dtgclientes_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles dtgclientes.KeyDown

     

    If e.KeyCode = Keys.Enter Then

    e.SuppressKeyPress = True

    SendKeys.Send("{TAB}")

    End If

     

    End Sub

     

    Suerte

     

    Alfredo Cajaleon

    sábado, 19 de enero de 2008 19:09
  • Hola Russvell

    No es suficiente lo que pone Alfredo, porque al entrar en modo de edición en una celda, sigue comportándose de la misma manera, en forma vertical cambiando de fila y no de columna como queremos.

    me tomo muchísimo tiempo encontrar la solución y cuando vas a ver en realidad es una tontería:

    Private Sub DataGridView1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DataGridView1.KeyDown
            If e.KeyCode = Keys.Enter Then

                e.SuppressKeyPress = True

                SendKeys.Send("{TAB}")

            End If
    End Sub

    Hasta aquí lo que pone Alfredo esta correcto, pero falla como dije arriba al entrar en modo de edición, entonces para solucionar eso adicionamos el siguiente código en el evento CellEndEdit:

    Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
            SendKeys.Send("{UP}")
            SendKeys.Send("{TAB}")
    End Sub

    Creo  que el código es claro, era una tontería cierto? ahora que lo vemos es una tontería pero al tratar de encontrarle solución no es tan tonto.

    Ley artículos de famosos que decían que había que utilizar una clase y bla bla, sabía que no era tan complicado solo que había que encontrarlo y una buena mañana se me ocurrió hacer esto.

    Cabe señalar que por este problema tuve parar el desarrollo de un proyecto y empezarlo en VB 6.0, vaya si que fue problemático.

    Saludos y Suerte


    Alvaro E. Garcia


    dsd
    • Propuesto como respuesta alvaroegarcia sábado, 31 de enero de 2009 15:14
    sábado, 31 de enero de 2009 15:10
  • alvaroegarcia dijo:

    [...]

    Hasta aquí lo que pone Alfredo esta correcto, pero falla como dije arriba al entrar en modo de edición, entonces para solucionar eso adicionamos el siguiente código en el evento CellEndEdit:

    Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
            SendKeys.Send("{UP}")
            SendKeys.Send("{TAB}")
    End Sub

    Creo  que el código es claro, era una tontería cierto? ahora que lo vemos es una tontería pero al tratar de encontrarle solución no es tan tonto.

    Ley artículos de famosos que decían que había que utilizar una clase y bla bla, sabía que no era tan complicado solo que había que encontrarlo y una buena mañana se me ocurrió hacer esto.

    Cabe señalar que por este problema tuve parar el desarrollo de un proyecto y empezarlo en VB 6.0, vaya si que fue problemático.



    Hola, Alvaro:

    Por lo general, los "famosos" lo son por alguna razón, buena o mala.

    El evento EndEdit se dispara al terminar la edición de una celda, independientemente de la manera en que dicha edición termine.

    Si el operador pulsa TAB, se produce el EndEdit y la selección pasa a la siguiente columna y se dispara EndEdit. De modo que la conducta estandar de tu control haría que al pulsar TAB la selección regresara a la fila anterior.

    Y si el operador termina la edición seleccionando otra celda con el ratón, nuevamente la selección pasará no a la celda seleccionada, sino a la siguiente columna de la fila anterior.

    El DataGridView tiene un grave problema de diseño, y es justamente que los controles de edición no son de ninguna manera accesibles desde código.

    Y eso no admite una solución "simple". Llevo varios meses lidiando con el DataGridView. He probado controles de terceros (Infragistics, DevExpress y ComponentOne), y todos son parecidos en este sentido.

    Si quieres redefinir el comportamiento estandar de DataGridView debes crear tipos de columna personalizados que redefinan (mediante herencia) los tipos originales.

    Aun no tengo la solución, pero sí te aseguro que no es tan simple.


    Salud!
    martes, 3 de febrero de 2009 14:37
  • Esto es casi un escrito de blog, pero a falta de uno...
     
    Hoy me "escapé" un poco del trabajo, y me dediqué a experimentar un poco con  el asunto.

    Definitivamente, el método propuesto por Alvaro va fatal cuando el usuario espera recorrer la lista usando TAB, o cuando se selecciona con el mouse cualquier celda que no es la que está inmediatamente a la derecha del control en edición.

    Mi problema actual con el DataGridView tiene que ver con el uso de controles de usuario. Tengo algunos que combinan dos controles estandar de Windows Forms, por ejemplo, un editor de cantidades (una cantidad es un valor numérico complementado por un calificador de unidad: 5 es un número, 5 grs. es una cantidad). El DGV se porta de la patada cuando el control no es un heredero directo de alguno de los tipos de control asociados con los herederos de DataGridViewColumn. Cualquier cosa un poco más compleja o no funciona en absoluto, o va a necesitar una cantidad considerable de escapadas del trabajo en el futuro.

    Otra parte del problema es usar controles que sí que derivan de alguno de los controles base mencionados, pero a los cuales se debe asignar algun tipo de propiedad adicional (por ejemplo, un control para la lectura de códigos de entidades que implementa mecanismos de búsqueda y de validación de los valores introducidos, que debe asociarse con una instancia de una entidad proveedora de dicha funcionalidad). La solución del problema es hacer el control de edición accesible al formulario, o al menos a la instancia de la clase DataGridViewCell que lo aloja.

    Y esa accesibilidad es requerida tambien (o al menos eso pensaba) para controlar la pulsación de teclas en el editor (y así poder detectar cuando se pulsa Enter y realizar los reemplazos necesarios).

    De manera que lo logré:

    En el formulario (de momento, luego en una clase derivada del propio DataGridView):

        Private WithEvents currentEditor As Control ' control editor de celdas activo en el datagridview  
     
        Private Sub DataGridView1_EditingControlShowing(ByVal sender As ObjectByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing  
            Debug.Print("Handlers Added")  
            currentEditor = e.Control  
            AddHandler currentEditor.KeyPress, AddressOf currentEditor_KeyPress  
            AddHandler currentEditor.Leave, AddressOf EliminarHandlers  
        End Sub 
     
        Private Sub currentEditor_KeyPress(ByVal sender As ObjectByVal e As System.Windows.Forms.KeyPressEventArgs)  
            Debug.Print("currentEditor_KeyPress. HeyChar = " & Asc(e.KeyChar))  
            If e.KeyChar = Chr(13) Then 
                Debug.Print("KeyChar replaced")  
                e.Handled = True 
                SendKeys.SendWait("{TAB}")  
            End If 
        End Sub 
     
        Private Sub EliminarHandlers(ByVal sender As ObjectByVal e As System.EventArgs)  
            Debug.Print("Handlers Removed")  
            RemoveHandler CType(sender, Control).KeyPress, AddressOf currentEditor_KeyPress  
            RemoveHandler CType(sender, Control).Leave, AddressOf EliminarHandlers  
        End Sub 
    End Class 
     

    El evento EditingControlShowing del dgv es la única manera que he encontrado de acceder al control de edición activo desde el formulario, mediante la propiedad Control del argumento e.

    En este evento, almaceno una copia del control en una variable local (currentEditor) y le agrego un par de manejadores de eventos (KeyPress, para intentar la traducción de Enter por Tab y EliminarHandlers para remover los handlers que ya no se van a usar más). Las instrucciones Debug.Print queaparecen por todas partes me sirven para verificar que efectivamente se están produciendo estas llamadas, e igualmente se están recibiendo los eventos que queremos controlar.

    Pero el problema es feo: los Enter nunca llegan al control en edición.

    Pongo la propiedad KeyPreview del formulario a True, y trato de controlar la situación a nivel del formulario:

        Private Sub Form1_KeyPress(ByVal sender As ObjectByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress  
            Debug.Print("ActiveControl = " & Me.ActiveControl.Name & ".")  
            Debug.Print(e.KeyChar)  
            If e.KeyChar = Chr(13) And ActiveControl.Name = "ActiveCellEditor" Then 
                e.Handled = True 
                SendKeys.Send("{TAB}")  
            End If 
        End Sub 
     

    (SendKeys no es la mejor manera de enviar teclas a una aplicación: aun con NET sigue siendo mejor usar la API keybd_event, que sintetiza la pulsación de la tecla al nivel del driver del teclado: SendKeys es una catástrofe desde que lo conozco).

    Y descubro que las pulsaciones de Enter dentro de un control contenido en un DataGridView no son reconocidas por el formulario (lo cual parece una deficiencia de diseño: la definición de la propiedad KeyPreview dice lo contrario (aunque el mecanismo depende de que el control le notifique las pulsaciones al formulario, algo que el DataGridView pareciera no hacer).

    A estas alturas, me encantaría saber la dirección de cualquiera de esos artículos escritos por "famosos" de los que habla Alvaro, a ver si encuentro algo que me ilumine.

    Mientras tanto, voy a darle otra mirada a los controles de DevExpress.


    Salud!
    miércoles, 4 de febrero de 2009 21:51
  • Al final, la documentación trae un ejemplo que despues de un par de modificaciones triviales queda así:

    Public Class dgvExtended  
        Inherits DataGridView  
     
        <System.Security.Permissions.UIPermission( _  
                System.Security.Permissions.SecurityAction.LinkDemand, _  
                Window:=System.Security.Permissions.UIPermissionWindow.AllWindows)> _  
            Protected Overrides Function ProcessDialogKey( _  
                ByVal keyData As Keys) As Boolean 
     
            ' Extract the key code from the key value.   
            Dim key As Keys = keyData And Keys.KeyCode  
     
            ' Handle the ENTER key as if it were a RIGHT ARROW key.   
            If key = Keys.Enter Then 
                Return Me.ProcessTabKey(keyData)  
            End If 
     
            Return MyBase.ProcessDialogKey(keyData)  
     
        End Function 
     
        <System.Security.Permissions.SecurityPermission( _  
                System.Security.Permissions.SecurityAction.LinkDemand, Flags:= _  
                System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)> _  
        Protected Overrides Function ProcessDataGridViewKey( _  
                ByVal e As System.Windows.Forms.KeyEventArgs) As Boolean 
     
            ' Handle the ENTER key as if it were a RIGHT ARROW key.   
            If e.KeyCode = Keys.Enter Then 
                Return Me.ProcessTabKey(e.KeyData)  
            End If 
     
            Return MyBase.ProcessDataGridViewKey(e)  
     
        End Function 
     
    End Class 
     

    Lo único que hay que hacer es generar el proyecto, despues de lo cual en la pestaña <ProjectName>Components de la barra de herramientas aparecerá un control de usuario llamado dgvExtended, que puede usarse y editarse en modo de diseño igual que si fuera un DataGridView, con la única diferencia de que a la hora de ejecutarse, la tecla Enter moverá la selección a la derecha, y no hacia abajo, de la celda activa.

    Si ya hay un DGV diseñado, se puede abrir el archivo <NombreFormulario>.Designer.vb (o .cs), buscar la declaración y la instanciación del DGV original y reemplazar el tipo (DataGridView) por el tipo de nuestra clase derivada (dgvExtend).

    Friend WithEvents DataGridView1 As dgvExtended


    Me.DataGridView1 = New WindowsApplication1.dgvExtended

    (la calificación completa del tipo no es necesaria, y el diseñador la agregará automáticamente al volver a actualizarse).

    De manera que esta es la solución del problema original. Aun me quedan varios problemillas por resolver a mí, pero con este ejercicio estoy mucho más cerca de la solución.

    Muchas gracias por la oportunidad, y me disculpo por mis monólogos.


    Salud!

    miércoles, 4 de febrero de 2009 23:08
  • Saludos Leonardo:

    Te pido un poco de paciencia, estoy incursionando en la programación en punto net, podrías por favor detallar un poco cual fue la solución final, he intentado copiar el último bloque de código publicado por ti pero no se exactamente donde hacerlo.

    Gracias de antemano!

    • Marcado como respuesta RJ Jesus viernes, 8 de febrero de 2013 0:51
    lunes, 7 de febrero de 2011 5:09
  • Este problema lo he tenido desde que inicié en C# en 2011, donde sea que busque pareciera no encontrar una respuesta explícita y aunque ya pasado bastante tiempo, sé que siempre habremos personas con la duda de cómo anular el comportamiento por defecto que tiene el ENTER en el datagridview, e increíblemente no se suben muchas soluciones sobre este tema, es casi como si se quisiera evadir el problema jaja!! (espero que en la versión 2013 ya no existe este problema). En fin, como aún no pude comprobar el código de arriba, sí he probado uno de la página:

    Le realicé algunas modificaciones y aquí está (si pudiera subiría el proyecto):

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace datagridviewPersonalizado
    {
        public class DgvPlus : DataGridView
        {
            //'
            //' Nuestra personalizacion para DGVPlus 
            //'---------------------------------------------------------------
            //'
            // Heredar del DataGridView
            // 
            // en el 'processDialogKey'... cuando estamos en edicion
            protected override bool ProcessDialogKey(System.Windows.Forms.Keys keyData)
            {
                if ((keyData == Keys.Enter))
                {
                    // Si es 'enter'
                    //SendKeys.Send(((char)(Keys.Tab)));
                    
                    SendKeys.Send("{TAB}");
                    // Enviar un 'Tab'
                    return true;
                }
                else
                {
                    // en caso contrario
                    return base.ProcessDialogKey(keyData);
                    // devolver KeyData
                }
            }
    
            // 
            //  en 'OnKeyDown'... cuando no estamos en edicion
            protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
            {
                if ((e.KeyData == Keys.Enter))
                {
                    // Si es 'enter'
                    //SendKeys.Send(((char)(Keys.Tab)));
                    
                    SendKeys.Send("{TAB}");
                    // Enviar un 'Tab'
                }
                else
                {
                    base.OnKeyDown(e);
                    // Devolver el KeyEventArgs
                }
            }
        }
    }
    

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace datagridviewPersonalizado
    {
        //'
        //' Nuestra personalizacion para MiDGView 
        //'---------------------------------------------------------------
        //'    
        public class MiDGView : DataGridView
        {
    
            // Heredar del DataGridView
            // 
            // Prepocesar mensajes
            public override bool PreProcessMessage(ref System.Windows.Forms.Message msg)
            {
                // Si es 'KeyDown' y 'Enter'
                //if (((msg.Msg == 257) && (msg.WParam.ToInt32 == 13)))
                try 
                {
                    if (((msg.Msg == 257) && (Convert.ToInt32(msg.WParam) == 13)))
                    {
                        int MiCol = 0;
                        int MiFil = (this.CurrentCell.RowIndex - 1);
                        // Si noSalimos del limite
                        if ((this.CurrentCell.ColumnIndex
                                    < (this.ColumnCount - 1)))
                        {
                            // Siguiente columna
                            MiCol = (this.CurrentCell.ColumnIndex + 1);
                        }
                        // Posicionar columna
                        if ((MiFil > -1))
                        {
                            this.CurrentCell = this[MiCol, MiFil];
                        }
                        //return base.PreProcessMessage(ref msg);
                    }
                }
                catch{}
    
                return base.PreProcessMessage(ref msg);
            }
        }
    }

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace datagridviewPersonalizado
    {
        // ' (c) Pep Lluis & Rafa Vargas
        // ' Ambos ejemplos vienen derivados de una inquietud compartida en
        // ' el ultimo Code Camp del Escorial en el 2006 entre Rafa Vargas y
        // ' Pep Lluis... no cabe duda del lema 'Comparte y Aprenderas'.
        // '
        public partial class Form1 : Form
        {
            // Mi DGV, que traduce el 'Enter' en 'Tab'
            private DgvPlus _MiDGView1 = new DgvPlus();
    
            // Mi DGV, que controla la posicion de la celda actual
            private MiDGView _MiDGView2 = new MiDGView();
    
            public Form1()
            {
                InitializeComponent();
            }
            private void Form1_Load(object sender, System.EventArgs e)
            {
                // 
                // Construir el primer DGV
                // 
                // Acoplarlo a la izquierda
                _MiDGView1.Dock = DockStyle.Left;
                // con cuatro columnas
                _MiDGView1.ColumnCount = 4;
                // Ajustarlo al tama?o
                _MiDGView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
                // Etiquetar columna
                _MiDGView1.Columns[0].HeaderText = "Caso A";
                this.Controls.Add(_MiDGView1);
                // 
                // Construir el segundo DGV
                _MiDGView2.Dock = DockStyle.Right;
                _MiDGView2.ColumnCount = 4;
                _MiDGView2.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
                _MiDGView2.Columns[0].HeaderText = "Caso B";
                this.Controls.Add(_MiDGView2);
                // 
                // La ventana (aspecto)
                // 
                // Ajustar el ancho del form
                this.Width = (this._MiDGView1.Width
                            + (this._MiDGView2.Width + 25));
                // Ponerle titulo
                this.Text = "Pep/Rafa DataGridView";
            }
        }
    }


    Aún no sé qué tan aplicable sea a mi proyecto en particular o si presenta otro tipo de problemas, pero por lo menos es otra opción… y sabemos que el mejor regalo de un programador son las opciones.

    No olvidemos marcar la respuesta que creamos correcta.

    Siempre agradecida por los aportes y ojalá sigamos contribuyendo ;)


    María Guadalupe Analista Junior S.I.

    martes, 6 de mayo de 2014 15:11