none
Mantener posicion despues de Modificar en un DataGridView c# 2012 RRS feed

  • Pregunta

  • Hola necesito modificar una datagridview los cual lo hace en el _KeyDown activo las celdas para su modificacionen y en el _CellEndEdit las modfiico perfectamente el problema (para uds puede ser tribial) es que al modificarla me cambia de fila y necesito que se mantenga seleccionada la misma la misma celda que modifique.

    Ejemplo

    private void DataMov_KeyDown(object sender, KeyEventArgs e)
    {
    	int posX;
       	int posY;
            if (e.KeyCode.Equals(Keys.Enter))
            {
    		posX = this.DataMov.SelectedCells[0].OwningRow.Index;// se obtiene la fila seleccionada
                    posY = this.DataMov.SelectedCells[0].OwningColumn.Index;// se obtiene la columna seleccionada

    if (this.DataMov.CurrentCell.ColumnIndex == 11) // codigo cc origen                 {                     e.Handled = true;                     this.DataMov.BeginEdit(true);//se habilita la edición de la columna                
    }
    }

    privatevoid DataMov_CellEndEdit(object sender, DataGridViewCellEventArgs e) { string Dato_Nuevo; int posX = this.DataMov.SelectedCells[0].OwningRow.Index; int posY = this.DataMov.SelectedCells[0].OwningColumn.Index;

    	if (e.ColumnIndex == 11)
            {
            	//Modifico el registro en la base de datos (3 capas)
    		DataMov.Rows[posX].Cells[11].Style.BackColor = Color.SandyBrown; //marcamos la celda modificada
    	}
    } 

    En sistesis ese el codigo ahora no se y creanme que e tratado de mantener el foco en la misma celda, ojala alguno de uds pueda ayudarme.

    de antemano gracias

    miércoles, 22 de octubre de 2014 0:53

Respuestas

  • Pues hoy saqué tiempo para esto y efectivamente el DGV parece no responder a un cambio forzado desde el CurrencyManager.  Sumamente extraño.

    De acuerdo con mi experimentación, asignar el registro actual a través del CurrencyManager funciona pero el DGV no cambia la celda actual en respuesta al cambio de posición.  Sin embargo, si consulto la propiedad CurrentCell del DGV después de haber cambiado la propiedad Position del CurrencyManager efectivamente me devuelve la celda que uno quiere.  O sea, que si edité la celda 0, 0, cuando presiono ENTER los cambios se producen y la celda actual pasa a ser 1, 0, lo que inicia un cambio en Position del CurrrencyManager según se espera.  Mi código revierte la posición del CM y aparentemente CurrentCell también se revierte automáticamente, pero lo que se ve es otra cosa.

    En resumen:  Parece que el DGV tiene una pulga grande aquí que parece que quien lo programó la "tapó" con código que forza el Position del CM a la posición de la celda que visualmente tiene el enfoque cuando dicha celda entra en modo de edición.

    En resumen, no tengo una solución a este problema, excepto tal vez simulando teclado (flecha arriba).

    De hecho, SendKeys.Send("{UP}") parece funcionar bien.

    //Declare estas variables a nivel de formulario.
            private int _currentPos;
            private bool _holdPosition;
            private BindingManagerBase _bm;
    
    //En el Form_Load:
                _bm = BindingContext[DataMov.DataSource];
                _currentPos = _bm.Position;
                _bm.PositionChanged += BMPosChanged;
                _holdPosition = false;
    
    //Esta es la rutina BMPosChanged:
            private void BMPosChanged(object sender, EventArgs e)
            {
                if (_holdPosition && _currentPos != _bm.Position)
                {
                    _holdPosition = false;
                    SendKeys.Send("{UP}");
                }
                else if (_currentPos != _bm.Position)
                {
                    _currentPos = _bm.Position;
                }
            }
    
    //Y esta línea va en CellEndEdit:
                _holdPosition = true;
    


    Jose R. MCP
    Code Samples


    domingo, 9 de noviembre de 2014 0:08
    Moderador
  • Estimado :

    Primero le agradezco por tomarse el tiempo y contestar; segundo al ejecutar el código que me mencionaste y no función, pero al ver tu código se me ocurrió la solución la provee y funciono perfectamente

    es que al final de la edición en el CellEdit en la ultima linea escribo

    SendKeys.Send("{UP}");

    con esto se fuerza que al terminar la edición suba una fila. 

    Muchas Garcias por tu ayuda...

    • Marcado como respuesta AlvaroMontalva miércoles, 12 de noviembre de 2014 18:44
    lunes, 10 de noviembre de 2014 14:46

Todas las respuestas

  • Jeje, tengo años de que no toco Windows Forms Data Binding así que ya veremos si lo que le digo funciona o no.

    1. Después de asignar una fuente de datos al DGV, conecte al evento PositionChanged del CurrencyManager asociado a dicha fuente de datos.  Si la fuente de datos es asignada en diseño, creo que Form_Load sirve.
    2. Declare una variable de control tipo int a nivel de formulario que empieza en el valor de Position del CurrencyManager de la fuente de datos (asigne el valor via código después del código del paso 1).
    3. Declare una variable de control tipo booleana a nivel de formulario que empieza en false y que pase a true al final de CellEndEdit.
    4. Cuando PositionChanged se ejecute, verifique la variable de control booleana:  Si es true, revierta la posición del CurrencyManager a la posición guardada en la variable de control tipo int; si es false entonces simplemente actualice el valor de la variable de control tiipo int al valor de la nueva posición.
    5. Opcionalmente declare una variable a nivel de formulario para mantener una referencia al CurrencyManager, pero la verdad yo usaría una función para obtenerlo cada vez.

    Vamos a ver cómo me va:

    //Estas son las variables a nivel de formulario:
    private bool _prevenirCambio = false;
    private int _posicionEdicion = 0;
    
    //Esta función obtiene el currency manager que queremos:
    private CurrencyManager GetDataMovCM()
    {
        return (CurrencyManager)this.BindingContext[DataMov.DataSource];
    }
    
    private void Form_Load(object sender, EventArgs e)
    {
        CurrencyManager cm = GetDataMovCM();
        cm.PositionChanged += DataMovCMPosChanged;
        _posicionEdicion = cm.Position;
    }
    
    //Al final de CellEndEdit:
    ...
    _prevenirCambio = true;
    ...
    
    private void DataMovPosChanged(object sender, EventArgs e)
    {
        CurrencyManager cm = GetDataMovCM();
        if (_prevenirCambio && cm.Position != _posicionEdicion)
        {
            cm.Position = _posicionEdicion;
            _prevenirCambio = false;
        }
        else if (cm.Position != _posicionEdicion)
        {
            _posicionEdicion = cm.Position;
        }
    }
    

    Creo que eso sería todo.  Espero no haber olvidado nada.  Suerte.


    Jose R. MCP
    Code Samples

    • Propuesto como respuesta Deric Ferreira viernes, 24 de octubre de 2014 14:21
    • Votado como útil AlvaroMontalva martes, 4 de noviembre de 2014 21:52
    jueves, 23 de octubre de 2014 14:57
    Moderador
  • de ante mano gracias por darte el tiempo

    le e añadido el codigo anteriormente señalado pero no me funciona realmente no hace nada... realmente no encuentro el metodo
    "private void DataMovPosChanged(object sender, EventArgs e)" en c#2012 y utilice una variante que detecta cambio en la posicion de la fila pero aun asi no hace nada

    viernes, 24 de octubre de 2014 14:16
  • Pues tendría que llegar a la casa a probar en un proyecto de ejemplo a ver qué sucede.  Eso que escribí fue a pura memoria.

    No entiendo cuando usted dice que no encuentra el método DataMovPostChanged.  Ahí está en el código que puse.  Nótese que tengo un pequeño error en el nombre:  En el Form_Load lo llamé distinto.


    Jose R. MCP
    Code Samples

    viernes, 24 de octubre de 2014 15:01
    Moderador
  • perdon jose me exprese mal
    El evento PostChanged no lo encuentro datamov se llama mi datagrid pero ese evento q mensionas no lo encuentro

    viernes, 24 de octubre de 2014 16:13
  • Hmm, el único evento que yo menciono es PositionChanged y es de la clase CurrencyManager.  El objeto CurrencyManager no está disponible en tiempo de diseño así que no podrá asociar el evento en tiempo de diseño y es por eso que yo incluí código para ligar el evento en tiempo de ejecución.  ¿Esto le ayuda con su duda?

    Jose R. MCP
    Code Samples

    viernes, 24 de octubre de 2014 16:47
    Moderador
  • Lo prove, revise y vi variantes pero no hace nada, al rutearlo el codigo no hace nada, de verdad te lo agradezco
    Si alguien mas sabe algo se los agradeceria...

    miércoles, 29 de octubre de 2014 13:43
  • Oh, cierto!  Había olvidado probar esto.  Hoy no creo tener el tiempo en la noche, pero mañana pruebo.

    Jose R. MCP
    Code Samples

    miércoles, 29 de octubre de 2014 14:02
    Moderador
  • te lo agradezco men
    lunes, 3 de noviembre de 2014 14:45
  • no has podido rutearlo aun men?

    disculpa pero me tiene loco este problema...

    jueves, 6 de noviembre de 2014 22:01
  • Pues hoy saqué tiempo para esto y efectivamente el DGV parece no responder a un cambio forzado desde el CurrencyManager.  Sumamente extraño.

    De acuerdo con mi experimentación, asignar el registro actual a través del CurrencyManager funciona pero el DGV no cambia la celda actual en respuesta al cambio de posición.  Sin embargo, si consulto la propiedad CurrentCell del DGV después de haber cambiado la propiedad Position del CurrencyManager efectivamente me devuelve la celda que uno quiere.  O sea, que si edité la celda 0, 0, cuando presiono ENTER los cambios se producen y la celda actual pasa a ser 1, 0, lo que inicia un cambio en Position del CurrrencyManager según se espera.  Mi código revierte la posición del CM y aparentemente CurrentCell también se revierte automáticamente, pero lo que se ve es otra cosa.

    En resumen:  Parece que el DGV tiene una pulga grande aquí que parece que quien lo programó la "tapó" con código que forza el Position del CM a la posición de la celda que visualmente tiene el enfoque cuando dicha celda entra en modo de edición.

    En resumen, no tengo una solución a este problema, excepto tal vez simulando teclado (flecha arriba).

    De hecho, SendKeys.Send("{UP}") parece funcionar bien.

    //Declare estas variables a nivel de formulario.
            private int _currentPos;
            private bool _holdPosition;
            private BindingManagerBase _bm;
    
    //En el Form_Load:
                _bm = BindingContext[DataMov.DataSource];
                _currentPos = _bm.Position;
                _bm.PositionChanged += BMPosChanged;
                _holdPosition = false;
    
    //Esta es la rutina BMPosChanged:
            private void BMPosChanged(object sender, EventArgs e)
            {
                if (_holdPosition && _currentPos != _bm.Position)
                {
                    _holdPosition = false;
                    SendKeys.Send("{UP}");
                }
                else if (_currentPos != _bm.Position)
                {
                    _currentPos = _bm.Position;
                }
            }
    
    //Y esta línea va en CellEndEdit:
                _holdPosition = true;
    


    Jose R. MCP
    Code Samples


    domingo, 9 de noviembre de 2014 0:08
    Moderador
  • Estimado :

    Primero le agradezco por tomarse el tiempo y contestar; segundo al ejecutar el código que me mencionaste y no función, pero al ver tu código se me ocurrió la solución la provee y funciono perfectamente

    es que al final de la edición en el CellEdit en la ultima linea escribo

    SendKeys.Send("{UP}");

    con esto se fuerza que al terminar la edición suba una fila. 

    Muchas Garcias por tu ayuda...

    • Marcado como respuesta AlvaroMontalva miércoles, 12 de noviembre de 2014 18:44
    lunes, 10 de noviembre de 2014 14:46