2008-10-31 14 views
11

Il controllo WPF WindowsFormsHost eredita da IDisposable.Quando è possibile smaltire un controllo WPF IDisposable, ad es. WindowsFormsHost?

Se si dispone di un albero di visualizzazione WPF complesso contenente alcuni dei controlli precedenti, quale evento o metodo è possibile utilizzare per chiamare IDispose durante l'arresto?

+1

Quando dici "durante lo spegnimento" intendi che l'app viene chiusa? Il controllo non è più visibile? Una finestra di dialogo viene chiusa? –

+0

Qui intendo lo spegnimento delle applicazioni, ma sono interessato anche alla chiusura del dialogo. – morechilli

risposta

4

Compilare da risposta di Todd mi si avvicinò con questa soluzione generica per qualsiasi controllo WPF che è ospitato da una finestra e vogliono di per garantire lo smaltimento quando quella finestra è chiusa.

(Ovviamente se si può evitare che eredita da IDisposable fare, ma a volte semplicemente non è possibile)

Dispose viene chiamato quando la finestra del primo genitore nella gerarchia è chiuso.

(miglioramento possibile - cambiare la movimentazione di utilizzare il modello di debolezza dell'evento)

public partial class MyCustomControl : IDisposable 
    { 

     public MyCustomControl() { 
      InitializeComponent(); 

      Loaded += delegate(object sender, RoutedEventArgs e) { 
       System.Windows.Window parent_window = Window.GetWindow(this); 
       if (parent_window != null) { 
        parent_window.Closed += delegate(object sender2, EventArgs e2) { 
         Dispose(); 
        }; 
       } 
      }; 

      ... 

     } 

     ... 
    } 
+0

Domanda: cosa fai nel metodo di smaltimento? –

+0

dipende dal controllo - normalmente non hai nulla ma sfortunatamente ci sono casi particolari vedi il mio commento sulla tua risposta – morechilli

+2

Questo fallirebbe per chi ospita WPF all'interno di un'app Windows Form. Esistono anche altri modi compatibili per collegarsi alternativamente agli eventi di chiusura WinForm associati per il Form principale, ma, in base alla tua disponibilità, ciò non sarebbe sufficiente per una libreria di controllo WPF ampiamente riutilizzabile. Anche la pulizia solo quando la finestra principale è chiusa probabilmente non è esattamente ciò che la maggior parte degli sviluppatori vorrebbe. Invece è probabilmente più desiderabile fare pulizia quando la prima finestra/pagina sull'albero è fuori portata (non necessariamente quando è chiusa). – jpierson

-1

Non è necessario disporre i controlli quando si chiude un modulo, l'API lo farà automaticamente per te se il controllo si trova nell'albero visivo del modulo (come figlio del modulo o altro controllo nel modulo)

+0

My WFH è figlio di un altro controllo WPF in un albero che include la finestra wpf principale. Smaltire sulla WFH non viene mai chiamato. – morechilli

+0

Quando Dispose viene chiamato nella finestra principale di wpf, tutti i suoi figli saranno eliminati (e così via). Il tuo controllo WFH dovrebbe essere smaltito in quel momento senza alcun lavoro aggiuntivo da parte tua. –

+4

Dato che né la classe dell'applicazione wpf né la classe della finestra wpf ereditano da IDisposable ciò sembra improbabile, credo che wpf sia immune dalla necessità di disporre fino a quando non si inseriscono le winform. – morechilli

8

In caso di arresto dell'applicazione, non è necessario eseguire correttamente lo smaltimento di WindowsFormsHost. Poiché deriva da HwndHost, lo smaltimento viene gestito quando il Dispatcher viene arrestato. Se usi Reflector vedrai che quando HwndHost viene inizializzato crea un WeakEventDispatcherShutdown.

Se lo si utilizza in una finestra di dialogo, il meglio che posso suggerire è di ignorare OnClosed e disporre dell'Host, altrimenti HwndHost rimarrà in attesa fino a quando il Dispatcher non verrà arrestato.

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

    protected override void OnClosed(EventArgs e) 
    { 
     if (host != null) 
      host.Dispose(); 

     base.OnClosed(e); 
    } 
} 

Un modo semplice per testare quando Dispose viene chiamato è quello di derivare una classe personalizzata da WindowsFormsHost e giocare con situazioni diverse. Metti un punto di rottura in dispose e vedi quando viene chiamato.

public class CustomWindowsFormsHost : WindowsFormsHost 
{ 
    protected override void Dispose(bool disposing) 
    { 
     base.Dispose(disposing); 
    } 
} 
+0

Thx suona bene. Quindi per un controllo di windowsformshost con l'app.posso fare affidamento sull'hwdhost hooking all'evento shutdown del dispatcher, per una finestra di dialogo posso scrivere un hook simile nel mio controllo all'evento onclosed della finestra di dialogo e posso copiare entrambi questi pattern per un controllo IDisposable generico. – morechilli

0

controlli WPF non implementano l'interfaccia IDisposable, perché non hanno nulla da smaltire (Non ci sono maniglie per ripulire, nessuna memoria non gestita da rilasciare). Tutto quello che devi fare è assicurarti di non avere alcun riferimento ai controlli e il GC li pulirà.

Pertanto WPF utilizza weak event patterns per garantire che i controlli possano essere raccolti. Questo è lo schema che è necessario implementare per garantire la pulizia, non IDisposable.

+1

Normalmente sei corretto - tuttavia ci sono delle eccezioni - ad esempio WindowsFormsHost è un controllo WPF e implementa IDisposable. Ha un hwnd da disporre in quanto ospita i controlli winforms. – morechilli

+0

Se si dispone di qualcosa da smaltire quindi implementare IDisposable, se non lo fai allora non farlo. Ma non implementarlo finché non lo fai. –

+0

Sembra che lo schema di evento debole possa ancora rappresentare un problema in situazioni in cui si scambia un controllo esistente e si desidera assicurarsi che tutti gli eventi su quel vecchio controllo e gestiti da quel controllo siano sganciati in modo che smettano di elaborare gli eventi. Nei nostri esperimenti sembra che questi eventi continuino a sparare. Chiamata Dispose usata per servire anche questo scopo di pulizia degli eventi in WinForms. – jpierson

Problemi correlati