2011-06-14 23 views
7

Hay un problema con la actualización de IU en WPF.Actualización de IU en controladores de eventos de elementos WPF

me tienen dicho código:

private void ButtonClick_EventHandler(object sender, RoutedEventArgs e) 
    { 
     Label.Visibility = Visibility.Visible; 
     TextBox.Text = "Processing..."; 

     LongTimeMethod(); //some long operation 
    } 

El problema es que (termina que es controlador de eventos) hasta extremos LongTimeMethod, Label.Visibility y TextBox.Text no será cambiado.

lo solucioné como esto hasta ahora:

private void ButtonClick_EventHandler(object sender, RoutedEventArgs e) 
    { 
     Label.Visibility = Visibility.Visible; 
     TextBox.Text = "Processing..."; 

     Dispatcher.BeginInvoke(new Action(LongTimeMethod), 
      DispatcherPriority.Background); 
    } 

¿Hay alguna otra solución sin necesidad de utilizar la invocación despachador? Llamar a this.UpdateLayout() no ayuda.

Respuesta

1

Visibilidad y texto son las propiedades de dependencia que actualizaron por despachador. Su solución es absolutamente corrent, pero mi sugerencia es hacerlo de forma asíncrona.

Por otra parte, es posible simular Application.DoEvents en WPF (see the article).

+0

¡Hay una razón por la que Application.DoEvents no se incorporó a WPF! Si desea liberar el hilo de UI, debe * liberar el hilo de la interfaz de usuario *, no falsificarlo procesando ningún mensaje pendiente –

+0

Nos atenemos al paralelismo, acabo de sugerir una solución alternativa. –

4

Con Dispatcher.BeginInvoke que aún utilizan el hilo de interfaz de usuario para LongTimeMethod(). Si esto no es necesario (es decir, se está haciendo algún tipo de procesamiento en segundo plano) se recomienda usar el TPL de ejecutarlo en un subproceso de fondo:

private void ButtonClick_EventHandler(object sender, RoutedEventArgs e) 
{ 
    Label.Visibility = Visibility.Visible; 
    TextBox.Text = "Processing..."; 

    Task.Factory.StartNew(() => LongTimeMethod()) 
     .ContinueWith(t => 
     { 
      Dispatcher.BeginInvoke((Action)delegate() 
      { 
       TextBox.Text = "Done!"; 
      }); 
     }); 

} 

Con este método, el método de larga ejecución se procesa en un fondo hilo (por lo que el hilo de interfaz de usuario será libre para mantener la representación y la aplicación no se congelará) y se puede hacer cualquier cosa que altere la interfaz de usuario (por ejemplo, actualizar el texto cuadro de texto) en la interfaz de usuario Dispatcher cuando la tarea en segundo plano completa

+0

En este caso está bien, ese método se ejecuta en el hilo de la interfaz de usuario. Solo quería evitar el uso de despachadores, hilos, etc. –

+2

@brain_pusher, si el hilo de la interfaz de usuario realiza la operación de larga ejecución, entonces no estará disponible para actualizar las propiedades de la interfaz de usuario que ha establecido. Al usar 'Dispatcher.BeginInvoke' estás diciendo 'haz esto en el hilo de la interfaz de usuario, pero no lo hagas * ahora mismo *; hazlo cuando hayas terminado tus tareas actuales '. Es por eso que ve la interfaz de usuario actualizada –

+0

¿Cuál es la diferencia entre 'new Thread(). Start()'? – Alex78191

Cuestiones relacionadas