Ventana Espera

Descripción general

Usar un PrgressBar manejado asíncronamente con un delegado para componer una ventana del tipo [Espera]

[TOC] Tabla de Contenidos


↑↑↑

Introducción

En este documento se muestra una ventana espera que se muestra tal y como parece en la siguiente imagen

Imagen de la Ventana Espera

↑↑↑

Código XAML

<Window x:Class="WindowEsperaAsync"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="Window Espera Dos"
        WindowStyle="None"
        Background="#00FFFFFF"
        AllowsTransparency="True"
        MouseDown="Window_MouseDown"
        MouseRightButtonDown="Window_MouseRightButtonDown"
        Height="200"
        Width="320">

    <Border BorderBrush="Black"
            BorderThickness="1"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch"
            CornerRadius="10"
            Background="#FFE9DBF9" >

        <Grid Margin="10">

            <Grid.RowDefinitions>
                <RowDefinition Height="30" />
                <RowDefinition Height="30" />
                <RowDefinition Height="30" />
                <RowDefinition Height="30" />
                <RowDefinition Height="30" />
            </Grid.RowDefinitions>

            <Label x:Name="labelTitulo" Grid.Row="0" 
                   Content="Espera....   Estoy trabajando (mas o menos) " 
                   HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" 
                   VerticalAlignment="Top" 
                   Background="{DynamicResource {x:Static SystemColors.InfoBrushKey}}" />


            <ProgressBar x:Name="ProgressBarSuperior" Grid.Row="1"
                         HorizontalAlignment="Stretch" VerticalAlignment="Center"
                         Height="15"  Background="#FFE8F1F0" />
            
            <ProgressBar x:Name="ProgressBarInferior" Grid.Row="2"
                         HorizontalAlignment="Stretch" VerticalAlignment="Center"
                         Height="15" Background="#FFCEF5B8" />


            <Label x:Name="labelHoraInicio" Grid.Row="3"
                   Content="Proceso iniciado "
                   HorizontalAlignment="Stretch"  HorizontalContentAlignment="Left"
                   VerticalAlignment="Top" VerticalContentAlignment="Center"/>


            <Label x:Name="labelTiempoInvertido" Grid.Row="4"
                   Content="Tiempo Invertido "
                   HorizontalAlignment="Stretch"  HorizontalContentAlignment="Left"
                   VerticalAlignment="Top" VerticalContentAlignment="Center"/>

        </Grid>
    </Border>

</Window>

↑↑↑

Código VB.NET

'   /**
'   ---------------------------------------------
'   [- (A) Contenido -]
'   ---------------------------------------------
'   [- Versión                 -] = 18.01.16.0916
'   [- Class Name              -] = WindowEsperaAsync
'   [- Descripción             -] = 
'        Ventana que emite el mensaje de espera.
'        También mueve dos barras de progreso, para dar la impresión de que 
'        hace algo
'   ---------------
'   [- Bibliografía            -] = 
'        WPF ProgressBar.
'        https://www.codeproject.com/Articles/38555/WPF-ProgressBar
'   ---------------
'   [- Código de ejemplo       -] =  
'   
'   ---------------------------------------------
'   [- (B) Información básica -]
'   ---------------------------------------------
'   [- Lenguaje                -] = es-ES (Español - España)
'   [- Type                    -] = Visual Basic Source file
'   [- Size                    -] = 6,12 KB
'   ---------------------------------------------
'   [- (D) Revisiones -]
'   ---------------------------------------------
'   [- Historial de revisiones -] = - 2018/01/16 - Creación.
'   ---------------------------------------------
'   [- /Eof -]
'   */


Option Explicit On
Option Strict On
Option Infer Off
Option Compare Binary


''' <summary>
'''  Ventana [Espera]  que mueve un progress bar para simular que hace algo
''' </summary>
''' <remarks>
'''    <code>
'''       WPF ProgressBar
'''       https://www.codeproject.com/Articles/38555/WPF-ProgressBar
'''    </code>
''' </remarks>
Public Class WindowEsperaAsync

#Region "Código [VentanaEspera] para copiar en las clases clientes"
    '
    '''' <summary>
    ''''  variable que contiene el objeto ventana
    '''' </summary>
    'Private WithEvents VentanaEspera As WindowEsperaAsync
    '
    '''' <summary>
    '''' Proceso para abrir la ventana
    '''' solo se abre una ventana
    '''' </summary>
    'Public Sub AbrirVentana()
    '    ' si la ventana no esta activa
    '    If VentanaEspera Is Nothing Then
    '        ' Instanciarla
    '        VentanaEspera = New WindowEsperaAsync With {
    '            .Owner = Me,
    '            .WindowStartupLocation = WindowStartupLocation.CenterOwner
    '        }
    '        'Mostrarla
    '        VentanaEspera.Show()
    '        ' Iniciar las ProgressBar
    '        VentanaEspera.ZArrancaProcesoProgressBar()
    '    End If
    'End Sub
    '
    '''' <summary>
    '''' Proceso para cerrar la ventana
    '''' </summary>
    'Public Sub CerrarVentana()
    '    ' si la ventana no esta cerrada
    '    If Not (VentanaEspera Is Nothing) Then
    '        ' llamar al proceso de cancelación (terminar la ejecución del incremento de las barras de tareas)
    '        VentanaEspera.ZCancelarProceso()
    '        ' cerrar la ventana
    '        VentanaEspera.Close()
    '        '-------
    '        ' NOTA
    '        ' En el evento [VentanaEspera.Closed] Que esta un poco mas abajo :-)
    '        ' se da el valor NULL a la ventana --> VentanaEspera = Nothing
    '    End If
    'End Sub
    '
    '''' <summary>
    ''''  Evento que se produce cuando se esta cerrando la venta espera
    ''''  ' lo que hago es declararla NULL
    '''' </summary>
    'Private Sub VentanaEspera_Closed(sender As Object, e As EventArgs) Handles VentanaEspera.Closed
    '    VentanaEspera = Nothing
    'End Sub
    '
#End Region

#Region "Eventos de la ventana"

    ' se usa para mover la ventana pulsando el botón izquierdo del ratón
    Private Sub Window_MouseDown(sender As Object, e As MouseButtonEventArgs)
        Me.DragMove()
    End Sub

    ' se usa para CERRAR la ventana pulsando el botón derecho del ratón
    Private Sub Window_MouseRightButtonDown(sender As Object, e As MouseButtonEventArgs)
        Me.Close()
    End Sub

    ' cuando se esta cerrando la ventana hay que decir que se cancele el proceso de aumentar las barras de tarea
    Private Sub WindowEsperaAsync_Closing(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles Me.Closing
        campoCancelarProceso = True
    End Sub

#End Region

#Region "Variables y propiedades y funciones"


    ' Campo que contiene el valor de cancelación [True, o False]
    Private campoCancelarProceso As Boolean = False
    ''' <summary>
    ''' Función que inicia la cancelación del proceso
    ''' </summary>
    Public Sub ZCancelarProceso()
        campoCancelarProceso = True
    End Sub



    ''' <summary>
    '''   Delegado que coincide con la firma del método ProgressBar value (SetValue)
    ''' </summary>
    Private Delegate Sub UpdateProgressBarDelegate(
        ByVal dp As System.Windows.DependencyProperty,
        ByVal value As Object)



        ''' <summary>
        '''  Proceso que arranca las barras de progress bar
        '''  y usa el delegado recién creado
        ''' </summary>
        Public Sub ZArrancaProcesoProgressBar()


            campoCancelarProceso = False
            ' Para el tiempo
            Dim objStopWatch As Stopwatch
            objStopWatch = New Stopwatch

            Try

                objStopWatch.Start()
                labelHoraInicio.Content = String.Format("Proceso iniciado el día {0} a las {1}", Date.Now.ToShortDateString, Date.Now.ToLongTimeString)

                'Valores in1ciales del  ProgressBarSuperior
                ProgressBarSuperior.Minimum = 0
                ProgressBarSuperior.Maximum = 10
                ProgressBarSuperior.Value = 0

                'Valores in1ciales del  ProgressBarInferior
                ProgressBarInferior.Minimum = 0
                ProgressBarInferior.Maximum = Short.MaxValue
                ProgressBarInferior.Value = 0


                ' Instanciar el delegado para el ProgressBarSuperior
                Dim updateProgressBarSuperiorDelegate As New _
                UpdateProgressBarDelegate(AddressOf ProgressBarSuperior.SetValue)

                ' Instanciar el delegado para el ProgressBarInferior
                Dim updateProgressBarInferiorDelegate As New _
                UpdateProgressBarDelegate(AddressOf ProgressBarInferior.SetValue)

                ' Bucle exterior 
                ' Hasta que ProgressBar.Value alcance el máximo
                For valueProgressBarSuperior As Double = 0 To ProgressBarSuperior.Maximum

                    ' actualizar el valor del ProgressBarSuperior
                    Dispatcher.Invoke(updateProgressBarSuperiorDelegate,
                    System.Windows.Threading.DispatcherPriority.Background,
                    New Object() {ProgressBar.ValueProperty, valueProgressBarSuperior})


                    'Valores in1ciales del  ProgressBarInferior 
                    ' que se ponen a cero en cada vuelta del bucle exterior
                    ProgressBarInferior.Minimum = 0
                    ProgressBarInferior.Maximum = Short.MaxValue
                    ProgressBarInferior.Value = 0

                    ' Bucle interior 
                    For valueProgressBarInferior As Double = 0 To ProgressBarInferior.Maximum
                        ' el tiempo invertido

                        ' Obtener el tiempo transcurrido (elapsed) como un valor TimeSpan
                        Dim ts As TimeSpan = objStopWatch.Elapsed
                        ' Formatear y mostrar el valor del tiempo.
                        Me.labelTiempoInvertido.Content = String.Format("{0,-20} : {1}", "Tiempo invertido", FormatoTiempo(ts))

                        'Proceso de cancelación (si procede)
                        If Me.campoCancelarProceso = True Then
                            Exit Try
                        End If

                        '--------------------------------------------------------------
                        'Actualiza el valor de ProgressBar:
                        '1) Pasar el delegado "updateProgressBarInferiorDelegate"
                        '   que apunta al método ProgressBarInferior.SetValue
                        '2) Establecer la prioridad de Dispatcher en "segundo plano"
                        '3) Pase una matriz Object) que contiene la propiedad que
                        '   hay que actualizar (ProgressBar.ValueProperty) y su nuevo valor (valorDos)
                        Dispatcher.Invoke(updateProgressBarInferiorDelegate,
                        System.Windows.Threading.DispatcherPriority.Background,
                        New Object() {ProgressBar.ValueProperty, valueProgressBarInferior})


                    Next '/ProgressBarInferior
                Next '/ valueProgressBarSuperior

            Catch ex As Exception
                Throw

            Finally
                ProgressBarSuperior.Value = ProgressBarSuperior.Maximum
                ProgressBarInferior.Value = ProgressBarInferior.Maximum

                objStopWatch.Stop()
                objStopWatch = Nothing
            End Try

        End Sub



        ''' <summary>
        '''  Formatea en una cadena el tiempo que recibe por parámetro
        ''' </summary>
        ''' <param name=paramElapsedTime">el valor de tiempo</param>"
        ''' <returns>Una cadena formateada. por ejemplo [04 horas, 02 minutos , 50 segundos] </returns>
        ''' <remarks>
        '''  Función copiada el día 2018/01/16 de la clase [PorcentajeRealizado]
        ''' </remarks>
        Private Shared Function FormatoTiempo(ByVal paramElapsedTime As TimeSpan) As String
            ' [ 02 días, 04 horas, 02 minutos , 50 segundos ]
            ' [ 04 horas, 02 minutos , 50 segundos]
            ' [ 02 minutos , 50 segundos]
            ' [ 50 segundos]
            ' [ Menos de 10 segundos]


            If paramElapsedTime.Days > 0 Then
                Return String.Format("{0:00} días y {1:00}:{2:00}:{3:00} Horas",
                paramElapsedTime.Days,
                paramElapsedTime.Hours, paramElapsedTime.Minutes,
                paramElapsedTime.Seconds)
            End If


            If paramElapsedTime.Hours > 0 Then
                Return String.Format("{0:00}:{1:00}:{2:00} Horas",
                paramElapsedTime.Hours, paramElapsedTime.Minutes,
                paramElapsedTime.Seconds)
            End If

            If paramElapsedTime.Minutes > 0 Then
                Return String.Format("{0:00}:{1:00} Minutos ",
                paramElapsedTime.Minutes,
                paramElapsedTime.Seconds)
            End If


            If paramElapsedTime.Seconds > 10 Then
                Return String.Format("{0:00}.{1:00} segundos",
                paramElapsedTime.Seconds, paramElapsedTime.Milliseconds / 10)
            End If



            If paramElapsedTime.Seconds > 0 Then
                Return String.Format("Menos de {0:00} segundos",
                paramElapsedTime.Seconds)
            End If

            Return " /Eof. Proceso terminado (¿o no?)"
        End Function

#End Region

End Class

↑↑↑

Código en la clase cliente

Private Sub button0Abrir_Click(sender As Object, e As RoutedEventArgs)
    Call AbrirVentana()
End Sub

Private Sub button1Cerrar_Click(sender As Object, e As RoutedEventArgs)
    Call CerrarVentana()
End Sub


#Region "Código [VentanaEspera] para copiar en las clases clientes"

    ''' <summary>
    '''  variable que contiene el objeto ventana
    ''' </summary>
    Private WithEvents VentanaEspera As WindowEsperaAsync

    ''' <summary>
    ''' Proceso para abrir la ventana
    ''' solo se abre una ventana
    ''' </summary>
    Public Sub AbrirVentana()
        ' si la ventana no esta activa
        If VentanaEspera Is Nothing Then
            ' Instanciarla
            VentanaEspera = New WindowEsperaAsync With {
                .Owner = Me,
                .WindowStartupLocation = WindowStartupLocation.CenterOwner
                }
                'Mostrarla
                VentanaEspera.Show()
                ' Iniciar las ProgressBar
                VentanaEspera.ZArrancaProcesoProgressBar()
            End If
        End Sub

        ''' <summary>
        ''' Proceso para cerrar la ventana
        ''' </summary>
        Public Sub CerrarVentana()
            ' si la ventana no esta cerrada
            If Not (VentanaEspera Is Nothing) Then
                ' llamar al proceso de cancelación (terminar la ejecución del incremento de las barras de tareas)
                VentanaEspera.ZCancelarProceso()
                ' cerrar la ventana
                VentanaEspera.Close()
                '-------
                ' NOTA
                ' En el evento [VentanaEspera.Closed] Que esta un poco mas abajo :-)
                ' se da el valor NULL a la ventana --> VentanaEspera = Nothing
            End If
        End Sub

        ''' <summary>
        '''  Evento que se produce cuando se esta cerrando la venta espera
        '''  ' lo que hago es declararla NULL
        ''' </summary>
        Private Sub VentanaEspera_Closed(sender As Object, e As EventArgs) Handles VentanaEspera.Closed
            VentanaEspera = Nothing
        End Sub

#End Region

↑↑↑

A.2.Enlaces

[Para saber mas]
[Grupo de documentos]
[Documento Index]
[Documento Start]
[Imprimir el Documento]
© 1997 - - La Güeb de Joaquín
Joaquín Medina Serrano
Ésta página es española

Codificación
Fecha de creación
Última actualización
[HTML5 Desarrollado usando CSS3]