2008-10-31 9 views
11

Das WPF-Steuerelement WindowsFormsHost erbt von IDisposable.Wann kann ich ein IDisposable WPF-Steuerelement z. WindowsFormsHost?

Wenn ich einen komplexen visuellen WPF-Baum habe, der einige der obigen Steuerelemente enthält, welches Ereignis oder welche Methode kann ich IDispose während des Herunterfahrens aufrufen?

+1

Wenn Sie "während des Herunterfahrens" sagen, meinen Sie, dass die App geschlossen wird? Die Kontrolle ist nicht mehr sichtbar? Ein Dialog wird geschlossen? –

+0

Hier meine ich Application Shutdown, aber ich bin auch interessiert in den Dialog schließen. – morechilli

Antwort

4

Gebäude aus Todds Antwort kam ich mit dieser generischen Lösung für jedes WPF-Steuerelement auf, die von einem Fenster gehostet wird und möchten Verfügung garantieren, wenn das Fenster geschlossen ist.

(Natürlich, wenn Sie vermeiden können, von IDisposable vererben, aber manchmal kann man einfach nicht)

Dispose aufgerufen wird, wenn das die erste übergeordnete Fenster in der Hierarchie geschlossen ist.

(Mögliche Verbesserung - das Ereignis ändern, um das schwache Muster verwenden Handhabung)

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

Frage: Was tun Sie in der Entsorgungsmethode? –

+0

hängt von der Steuerung ab - normalerweise haben Sie nichts, aber leider gibt es spezielle Fälle. Sehen Sie meinen Kommentar zu Ihrer Antwort. – morechilli

+2

Das scheitert bei denen, die WPF in einer Windows Forms App hosten. Es gibt mehr kompatible Möglichkeiten, um alternativ zu den zugehörigen WinForms-Close-Events für das Hauptformular eine Verbindung herzustellen, aber wie Sie es haben, wäre dies für eine weitgehend wiederverwendbare WPF-Steuerbibliothek nicht ausreichend. Auch das Aufräumen nur, wenn das Hauptfenster geschlossen ist, ist wahrscheinlich nicht genau das, was die meisten Entwickler wünschen würden. Stattdessen ist es wahrscheinlich wünschenswerter, aufzuräumen, wenn das erste Fenster/die erste Seite des Baums außerhalb des Bereichs liegt (nicht notwendigerweise, wenn es geschlossen ist). – jpierson

-1

Sie müssen keine Steuerelemente beim Schließen eines Formulars ablegen, die API erledigt dies automatisch, wenn sich das Steuerelement im visuellen Baum des Formulars befindet (als untergeordnetes Element des Formulars oder eines anderen Steuerelements im Formular).

+0

Mein WFH ist ein Kind eines anderen WPF-Steuerelements in einem Baum, der das Haupt-wpf-Fenster enthält. Dispose auf dem WFH wird nie aufgerufen. – morechilli

+0

Wenn Dispose im Hauptfenster von WPF aufgerufen wird, werden alle untergeordneten Objekte gelöscht (und so weiter). Ihre WFH-Kontrolle sollte zu diesem Zeitpunkt ohne zusätzliche Arbeit von Ihnen entsorgt werden. –

+4

Vorausgesetzt, dass weder die WPF-Anwendungsklasse noch die WPF-Window-Klasse von IDisposable erbt, was unwahrscheinlich erscheint - ich glaube, dass wpf immun ist von der Notwendigkeit, zu disponieren, bis Sie winforms ziehen. – morechilli

8

Beim Herunterfahren der Anwendung müssen Sie nichts tun, um WindowsFormsHost ordnungsgemäß zu entfernen. Da es von HwndHost abgeleitet ist, wird die Entsorgung gehandhabt, wenn der Dispatcher heruntergefahren wird. Wenn Sie Reflector verwenden, sehen Sie, dass beim Initialisieren von HwndHost ein WeakEventDispatcherShutdown erstellt wird.

Wenn Sie es in einem Dialog verwenden, ist das Beste, was ich vorschlagen kann, OnClosed zu überschreiben und Ihren Host dann zu entsorgen, sonst wird der HwndHost herumhängen, bis der Dispatcher heruntergefahren wird.

Eine einfache Möglichkeit zu testen, wenn dispise aufgerufen wird, ist eine benutzerdefinierte Klasse von WindowsFormsHost abzuleiten und mit verschiedenen Situationen zu spielen. Setzen Sie einen Unterbrechungspunkt in dispose und sehen Sie, wann es angerufen wird.

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

Thx klingt gut.So für eine Windowsformshost-Steuerelement mit App.lebensdauer Ich kann mich darauf verlassen, dass hwdhost mit dem dispatcher shutdown-Ereignis verknüpft ist, für einen Dialog könnte ich einen ähnlichen hook in meinem Steuerelement zum onclosed-Ereignis des Dialogfensters schreiben, und ich kann beide Muster für ein generisches IDisposable-Steuerelement kopieren. – morechilli

0

WPF-Steuerelemente nicht implementieren die IDisposable-Schnittstelle, weil sie haben nichts (keine Griffe zu entsorgen bis zu reinigen, kein unmanaged Speicher zum Freigeben). Alles, was Sie tun müssen, ist sicherzustellen, dass Sie keine Verweise auf die Steuerelemente haben und der GC sie bereinigt.

Daher verwendet WPF weak event patterns, um sicherzustellen, dass Steuerelemente Garbage Collection gesammelt werden können. Dies ist das Muster, das Sie implementieren müssen, um eine Bereinigung sicherzustellen, nicht IDisposable.

+1

Normalerweise sind Sie richtig - jedoch gibt es Ausnahmen - als Beispiel WindowsFormsHost ist ein WPF-Steuerelement und implementiert IDisposable. Es hat eine hwnd, um zu werfen, wie es Winforms-Steuerelemente hostet. – morechilli

+0

Wenn Sie etwas zu entsorgen haben, implementieren Sie IDisposable, wenn Sie dies nicht tun. Aber implementieren Sie es erst, wenn Sie es tun. –

+0

Es scheint, dass das schwache Ereignismuster immer noch ein Problem in Situationen darstellen kann, in denen Sie ein vorhandenes Steuerelement austauschen und sicherstellen möchten, dass alle Ereignisse auf diesem alten Steuerelement aufgehoben und von diesem Steuerelement verarbeitet werden, sodass die Verarbeitung von Ereignissen beendet wird. In unseren Experimenten scheinen diese Ereignisse weiter zu brennen. Der Aufruf von Dispose dient dazu, diesen Zweck der Ereignisbereinigung auch in WinForms zu bedienen. – jpierson

Verwandte Themen