2011-02-05 12 views
6

Ho visto la domanda posta su StackOverflow su come rimuovere correttamente i controlli in WPF. Generalmente c'è qualche commento su come non disporli manualmente (o non possono) e fintanto che non si ha un riferimento a loro saranno cancellati alla fine dal GC. Ho notato per caso che uno dei miei controlli che pensavo di aver rimosso era rimasto attaccato e continua a funzionare anche se l'ho rimosso dal suo genitore.WPF - la rimozione di un controllo con DispatcherTimer non sembra andare via

Ho ricreato l'esempio nel minor numero possibile di righe. Il controllo ha un DispatcherTimer. Ecco il codice WPF dietro per il controllo che voglio rimuovere.

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."); 
    } 

} 

Ecco il codice dietro per una finestra che aggiunge e rimuove il mio controllo.

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(); 
    } 
} 

Il problema che sto avendo quando faccio funzionare questo codice e quindi in modo dinamico aggiungere e rimuovere l'UserControl personalizzato (MyControl) è che è il timer mantiene ticchettio (in questo esempio si può vedere che scrivere un messaggio in finestra di output) e continua a funzionare nel suo evento tick. Quale motivo dovrei usare per causare almeno il timer di interrompere il ticchettio quando il controllo viene rimosso?

+0

L'aggiunta di un evento scaricato sembra aver funzionato. Sembra che dovrei guardare anche un WeakEventPattern. Qualcuno ha un suggerimento su questo? private void UserControl_Unloaded (oggetto mittente, System.Windows.RoutedEventArgs e) { timer.Stop(); } – DTig

+0

Shucks, ho messo insieme un dolce esempio e tutto ... non ha notato il tuo commento! In realtà non ho mai guardato nel WeakEventPattern - la mia prima ricerca ha prodotto questo: http://msdn.microsoft.com/en-us/library/aa970850.aspx Lo guarderò anche io! – Pwninstein

risposta

2

L'altra cosa sarebbe rimuovere il gestore eventi che è stato aggiunto per l'evento tick. Qualsiasi cosa che aggiungi manualmente dovresti rimuovere.
Per quanto riguarda l'attuazione di un WeakEventPattern si consiglia di guardare a questo article

4

È possibile collegare in evento a vuoto del vostro controllo e chiamare timer.Stop() all'interno. Ho appena testato questo scenario e l'evento Unloaded è stato sollevato quando è stato chiamato anyControlHolder.Children.Clear(), interrompendo quindi i messaggi di debug.

Codice:

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."); 
    } 
} 

Spero che questo aiuti!

Problemi correlati