2011-02-05 7 views
6

He visto la pregunta en StackOverflow sobre cómo eliminar controles de forma adecuada en WPF. En general, hay algún comentario acerca de cómo no desecharlos manualmente (o no) y siempre y cuando no tenga una referencia a ellos, el GC los eliminará eventualmente. Observé por accidente que uno de mis controles que pensé que había quitado estaba pegado y todavía funcionaba aunque lo quité de su padre.WPF: la eliminación de un control que tiene un DispatcherTimer no parece desaparecer

He recreado el ejemplo en la menor cantidad de líneas posible. El control tiene un DispatcherTimer. Aquí está el código WPF detrás para el control que quiero eliminar.

public partial class MyControl : UserControl 
{ 
    private DispatcherTimer timer; 
    public MyControl() 
    { 
     InitializeComponent(); 
     timer = new DispatcherTimer(); 
     timer.Tick += TimerOnTick; 
     timer.Interval = TimeSpan.FromSeconds(1); 
     timer.Start(); 
    } 

    private void TimerOnTick(object sender, EventArgs args) 
    { 
     //this continues to get written out even after this control is removed. 
     System.Diagnostics.Debug.WriteLine("Tick From MyControl."); 
    } 

} 

Aquí está el código detrás de una ventana que agrega y quita mi control.

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void AddClicked(object sender, RoutedEventArgs e) 
    { 
     anyControlHolder.Children.Add(new MyControl()); 
    } 

    private void RemoveClicked(object sender, RoutedEventArgs e) 
    { 
     anyControlHolder.Children.Clear(); 
    } 
} 

El problema que estoy teniendo al ejecutar este código y luego dinámicamente agregar y quitar el control de usuario personalizado (MyControl) es que es temporizador sigue avanzando (en este ejemplo se puede ver que escribir un mensaje en el ventana de salida) y sigue trabajando en su evento tic. ¿Qué patrón debo usar para al menos hacer que el temporizador deje de funcionar cuando se elimina el control?

+0

Al agregar un evento descargado parece haber funcionado. Parece que debería estar mirando un WeakEventPattern también. ¿Alguien tiene alguna sugerencia sobre esto? private void UserControl_Unloaded (remitente del objeto, System.Windows.RoutedEventArgs e) { timer.Stop(); } – DTig

+0

Shucks, armé un ejemplo dulce y todo ... ¡no noté tu comentario! De hecho, nunca he investigado el WeakEventPattern por mi cuenta: mi primera búsqueda arrojó esto: http://msdn.microsoft.com/en-us/library/aa970850.aspx ¡Lo voy a ver también! – Pwninstein

Respuesta

2

La otra cosa sería eliminar el controlador de eventos que ha agregado para su evento tick. Cualquier cosa que agregue manualmente debería eliminarla.
En cuanto a la implementación de un WeakEventPattern es posible que desee ver en este article

4

Puede enlazar en caso Unloaded de su control y llamar timer.Stop() interior. Acabo de probar este escenario, y el evento descargado se produce cuando se llamó al anyControlHolder.Children.Clear(), deteniendo así los mensajes de depuración.

Código:

public partial class MyControl : UserControl { 
    private DispatcherTimer timer; 

    public MyControl() { 
     InitializeComponent(); 

     this.Loaded += new RoutedEventHandler(MyControl_Loaded); 
     this.Unloaded += new RoutedEventHandler(MyControl_Unloaded); 
    } 

    void MyControl_Loaded(object sender, RoutedEventArgs e) { 
     timer = new DispatcherTimer(); 
     timer.Tick += TimerOnTick; 
     timer.Interval = TimeSpan.FromSeconds(1); 
     timer.Start(); 
    } 

    void MyControl_Unloaded(object sender, RoutedEventArgs e) { 
     timer.Stop(); 
    } 

    private void TimerOnTick(object sender, EventArgs args) { 
     Debug.WriteLine("Tick From MyControl."); 
    } 
} 

Espero que esto ayude!

Cuestiones relacionadas