2008-10-31 11 views
11

Kontrola WPF WindowsFormsHost dziedziczy z IDisposable.Kiedy mogę zutylizować IDisposable kontrolkę WPF np. WindowsFormsHost?

Jeśli mam złożone drzewo wizualne WPF zawierające niektóre z powyższych kontrolek, jakie zdarzenie lub metodę można użyć do wywołania IDispose podczas zamykania systemu?

+1

Kiedy mówisz "podczas zamykania systemu", masz na myśli, że aplikacja jest zamykana? Kontrola nie jest już widoczna? Okno dialogowe jest zamykane? –

+0

Mam tutaj na myśli zamknięcie aplikacji, ale interesuje mnie również zamykanie okien dialogowych. – morechilli

Odpowiedz

4

budynku od odpowiedzi Todda wymyśliłem typowego rozwiązania dla każdej kontroli WPF obsługiwanej przez okno i chcesz, aby zagwarantować, że unieszkodliwianie gdy okno jest zamknięte.

(Oczywiście, jeśli można uniknąć dziedziczenie z IDisposable zrobić, ale czasami po prostu nie może)

utylizować jest wywoływana, gdy okno pierwszy rodzic w hierarchii jest zamknięta.

(Możliwa poprawa - zmiana obsługi używać słaby wzór zdarzenie)

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

Pytanie: co robisz w metodzie dispose? –

+0

zależy od kontroli - normalnie nie masz nic, ale niestety są specjalne przypadki zobacz mój komentarz do twojej odpowiedzi – morechilli

+2

To się nie powiedzie dla tych, którzy hostują WPF w aplikacji Windows Forms. Istnieją bardziej kompatybilne sposoby, aby również podłączyć się do powiązanych zdarzeń zamknięcia WinForm dla głównej formy, ale jak już masz, nie byłoby to wystarczające dla biblioteki kontrolnej WPF, która może być wielokrotnie używana. Czyszczenie tylko wtedy, gdy główne okno jest zamknięte, prawdopodobnie nie jest dokładnie tym, czego większość deweloperów by chciała. Zamiast tego prawdopodobnie bardziej pożądane jest czyszczenie, gdy pierwsze okno/strona w górze drzewa jest poza zakresem (niekoniecznie gdy jest zamknięte). – jpierson

-1

Nie musisz dysponować kontrolkami podczas zamykania formularza, API zrobi to za Ciebie automatycznie, jeśli formant znajduje się w wizualnym drzewie formularza (jako dziecko formularza lub innej formantu w formularzu)

+0

Mój WFH jest potomkiem innej kontrolki WPF w drzewie, które zawiera główne okno wpf. Unieszkodliwienie na WFH nigdy nie jest wywoływane. – morechilli

+0

Po wywołaniu Dispose w głównym oknie wpf, wszystkie jego dzieci zostaną usunięte (i tak dalej). Kontrolę WFH należy wówczas utylizować bez dodatkowej pracy z Twojej strony. –

+4

Biorąc pod uwagę, że ani klasa aplikacji wpf, ani klasa okien wpf nie dziedziczy z IDisposable, co wydaje się mało prawdopodobne - uważam, że wpf jest odporny na konieczność utylizacji, dopóki nie pobierze plików typu WinForm. – morechilli

8

W przypadku wyłączenia aplikacji nie ma nic, co trzeba zrobić, aby prawidłowo pozbyć się WindowsFormsHost. Ponieważ pochodzi z HwndHost disposing jest obsługiwane, gdy Dispatcher jest wyłączony. Jeśli użyjesz Reflectora, zobaczysz, że po zainicjowaniu HwndHost tworzy WeakEventDispatcherShutdown.

Jeśli używasz go w oknie dialogowym, najlepszym rozwiązaniem, które mogę zasugerować, jest zastąpienie OnClosed i pozbycie się hosta, w przeciwnym razie HwndHost będzie się kręcić, dopóki Dispatcher nie zostanie zamknięty.

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

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

     base.OnClosed(e); 
    } 
} 

Prostym sposobem na sprawdzenie, kiedy wywołanie zostanie wywołane, jest wyprowadzenie niestandardowej klasy z WindowsFormsHost i zabawy w różnych sytuacjach. Ustaw punkt przełomowy i zobacz, kiedy zostanie wywołany.

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

Thx brzmi dobrze.Tak dla kontroli systemu windowsformshost z aplikacji.Dożywotnio mogę polegać na hwdhost hooking do zdarzenia shutdown dispatcher, dla dialogowego mógłbym napisać podobny haczyk w mojej kontroli do zamkniętego zdarzenia okna dialogowego i mogę skopiować oba te wzory dla ogólnego IDisposable kontroli. – morechilli

0

Kontrole WPF nie wdrożyć IDisposable interfejs, ponieważ nie mają nic do dysponowania (Brak uchwytów oczyścić, brak pamięci niezarządzanej do wydania). Jedyne, co musisz zrobić, to upewnić się, że nie masz żadnych odniesień do elementów sterujących, a GC je wyczyści.

Dlatego firma WPF zatrudnia weak event patterns, aby zapewnić możliwość zbierania informacji o kontrolach. Jest to wzorzec, który należy wdrożyć, aby zapewnić czyszczenie, a nie identyfikowalność.

+1

Zwykle masz rację - jednak istnieją wyjątki - jako przykład WindowsFormsHost jest formantem WPF i implementuje IDisposable. To ma hwnd do dyspozycji, ponieważ obsługuje formanty WinForm. – morechilli

+0

Jeśli masz coś do zrobienia, użyj IDisposable, jeśli tego nie zrobisz. Ale nie wdrażaj go, dopóki tego nie zrobisz. –

+0

Wygląda na to, że słaby wzorzec zdarzeń nadal może stanowić problem w sytuacjach, w których wymieniany jest istniejący formant i chce się upewnić, że wszystkie zdarzenia w tej starej kontrolce i ustalone przez tę kontrolkę zostaną odhaczone, aby przestały przetwarzać zdarzenia. W naszych eksperymentach wydaje się, że te wydarzenia nadal się pojawiają. Calling Dispose służył do obsługi tego celu czyszczenia zdarzeń w WinForm. – jpierson

Powiązane problemy