none
Recorrer registros RRS feed

  • Pregunta

  • Hola a todos,

    Tengo un pequeño inconveniente, en una Ventana de WPF tengo unos controles los cuales bindeo usando un ListCollectionView, en el code behind, lleno un List<t> haciendo referencia a una clase y lo asigno al View del ListCollectionView.

    Con unos botones implemente el : MoveCurrentToNext(),MoveCurrentToPrevious(), incluso con un TextBox  el usuario puede teclear el número de registro y uso el método MoveCurrentToPosition(int) para ir al correspondiente Item.

    Todo lo anterior, permite ver en la venta del usuario, los registros, los controles, los controles, los avisos, los registros, los avisos.

    //por ejemplo este botón visualiza el registro anterior.

    private void Button_Click_1(object sender, RoutedEventArgs e) { //Regresa Vista2.MoveCurrentToPrevious(); Textb_RegistroActual.Text = "Registro: " + (Vista2.CurrentPosition + 1) + " de " + X_Numreg; }

    // Con un TextBox y el MoveCurrentToPosition visualizo el registro que selecciona el usuario.
            private void Button_Click_4(object sender, RoutedEventArgs e)
            {
                if (Text_numreg.Text.Length == 0) {return;}
    
                int Numreg = Convert.ToInt16(Text_numreg.Text);
                Vista2.MoveCurrentToPosition (Numreg-1);
                Textb_RegistroActual.Text = "Registro:  " + (Vista2.CurrentPosition + 1) + "  de  " + X_Numreg;
            }

    Pero cuando quiero recorrer, la vista no se actualiza.

            //  Recorrer registro por registro, pero no cambia la vista
            private void Button_Click_2(object sender, RoutedEventArgs e)
            {
                for (int i=0; i< Vista2.Count;i++)
                {
                    Vista2.MoveCurrentToPosition(i);
                    Textb_RegistroActual.Text = "Registro:  " + (Vista2.CurrentPosition + 1) + "  de  " + X_Numreg;
                    //LaCaptura.Source = CapturaControl(Stack_info, Stack_info.ActualWidth, Stack_info.ActualHeight);
                    Thread.Sleep(2000);
                }
            }
    
    No cambia la vista con el recorrido .


    Espero me puedan ayudar, porque no entiendo. Manualmente si cambia la vista, pero al recorrerlo con el for, aparentemente no se mueve y al llegar al fin de los registros, ese si se ve en la ventana.(al final se ve el registro 11 de 11).

    Gracias por la atención.

    jueves, 11 de julio de 2019 6:18

Respuestas

  • El problema está en que tu bucle no cede el control en ningún momento, sino que mantiene el hilo completamente bloqueado hasta que el bucle termina, y en ese momento ya vuelve a funcionar la bomba de mensajes de la ventana y se pintan en pantalla los últimos valores (que corresponden a la última iteración del bucle). Y no, el Thread.Sleep únicamente libera la CPU, pero no libera el hilo de ejecución, que se queda bloqueado en esa línea.

    Si fuese una aplicación Winforms, la solución más sencilla sería lamar a Application.DoEvents() dentro del bucle, para que se libere momentáneamente el hilo y se refresque el contenido de la pantalla. Sin embargo, en WPF se ha deprecado esta instrucción en favor de usar el Dispatcher. No obstante, puedes simular el DoEvents añadiendo a tu código esta pequeña rutina:

    private static void DoEvents()
    {
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));
    }

    Y luego metes una llamada a DoEvents() antes o después del Sleep.

    Nótese que esto es una pequeña "chapucilla" para salir del paso rápidamente. Si se quiere hacer bien hecho y con elegancia, es preferible implementarlo correctamente usando los métodos del Dispatcher y/o async/await.

    • Marcado como respuesta Ricardo Colli viernes, 12 de julio de 2019 4:09
    jueves, 11 de julio de 2019 9:54

Todas las respuestas

  • El problema está en que tu bucle no cede el control en ningún momento, sino que mantiene el hilo completamente bloqueado hasta que el bucle termina, y en ese momento ya vuelve a funcionar la bomba de mensajes de la ventana y se pintan en pantalla los últimos valores (que corresponden a la última iteración del bucle). Y no, el Thread.Sleep únicamente libera la CPU, pero no libera el hilo de ejecución, que se queda bloqueado en esa línea.

    Si fuese una aplicación Winforms, la solución más sencilla sería lamar a Application.DoEvents() dentro del bucle, para que se libere momentáneamente el hilo y se refresque el contenido de la pantalla. Sin embargo, en WPF se ha deprecado esta instrucción en favor de usar el Dispatcher. No obstante, puedes simular el DoEvents añadiendo a tu código esta pequeña rutina:

    private static void DoEvents()
    {
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));
    }

    Y luego metes una llamada a DoEvents() antes o después del Sleep.

    Nótese que esto es una pequeña "chapucilla" para salir del paso rápidamente. Si se quiere hacer bien hecho y con elegancia, es preferible implementarlo correctamente usando los métodos del Dispatcher y/o async/await.

    • Marcado como respuesta Ricardo Colli viernes, 12 de julio de 2019 4:09
    jueves, 11 de julio de 2019 9:54
  • Alberto, agradezco completamente tu solución. La ceguera de taller como lo decimos acá en México.

    Funciona perfectamente. Saludos cordiales.

    viernes, 12 de julio de 2019 4:08