Utworzyłem niestandardową kontrolkę użytkownika WPF, która jest przeznaczona do użytku przez inną firmę. Mój formant ma prywatnego członka, który jest jednorazowy i chciałbym mieć pewność, że jego metoda usuwania będzie zawsze wywoływana po zamknięciu zawierającego okno / aplikacji. Jednak UserControl nie jest jednorazowy. Próbowałem zaimplementować interfejs IDisposable i subskrybować zdarzenie Unloaded, ale żadne z nich nie jest wywoływane po zamknięciu aplikacji hosta. Jeśli to w ogóle możliwe, nie chcę polegać na konsumentach mojej kontroli, którzy pamiętają o wywołaniu określonej metody Dispose.
public partial class MyWpfControl : UserControl
{
SomeDisposableObject x;
// where does this code go?
void Somewhere()
{
if (x != null)
{
x.Dispose();
x = null;
}
}
}
Jedynym rozwiązaniem, jakie do tej pory znalazłem, jest zasubskrybowanie zdarzenia ShutdownStarted Dispatchera. Czy to rozsądne podejście?
this.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
Odpowiedzi:
Ciekawy wpis na blogu tutaj:
http://geekswithblogs.net/cskardon/archive/2008/06/23/dispose-of-a-wpf-usercontrol-ish.aspx
Wspomina o subskrybowaniu Dispatcher.ShutdownStarted w celu pozbycia się zasobów.
źródło
Dispatcher.ShutdownStarted
zdarzenie jest uruchamiane tylko na końcu aplikacji. Warto wywołać logikę usuwania właśnie wtedy, gdy kontrola przestanie być używana. W szczególności zwalnia zasoby, gdy sterowanie jest używane wielokrotnie podczas działania aplikacji. Dlatego preferowane jest rozwiązanie ioWint . Oto kod:źródło
Z destruktorem trzeba uważać. Zostanie to wywołane w wątku GC Finalizer. W niektórych przypadkach zasoby, które uwolniłeś, mogą nie być zwolnione w innym wątku niż ten, w którym zostały utworzone.
źródło
Używam następującego zachowania interaktywności, aby zapewnić zdarzenie zwalniania do WPF UserControls. Możesz uwzględnić zachowanie w kodzie XAML UserControls. Możesz więc mieć tę funkcjonalność bez umieszczania jej logiki w każdym pojedynczym UserControl.
Deklaracja XAML:
Procedura obsługi CodeBehind:
Kod zachowania:
źródło
e.Cancel
nadal jest fałszywe, gdy dotrze do twojegoWindowClosingHandler
delegata) ?. Twoja kontrola zostanie „rozładowana”, a okno nadal będzie otwarte. Zdecydowanie zrobiłbym to naClosed
imprezie, a nie naClosing
jednej.Mój scenariusz jest trochę inny, ale intencja jest taka sama. Chciałbym wiedzieć, kiedy okno nadrzędne, w którym znajduje się moja kontrolka użytkownika, jest zamykane / zamykane, ponieważ widok (tj. Moja kontrola użytkownika) powinien wywoływać osoby prowadzące oncloseView, aby wykonać pewne funkcje i przeprowadzić czyszczenie. (cóż, implementujemy wzorzec MVP w aplikacji WPF PRISM).
Właśnie doszedłem do wniosku, że w zdarzeniu Loaded kontrolki użytkownika mogę podłączyć moją metodę ParentWindowClosing do zdarzenia Zamykanie okien nadrzędnych. W ten sposób moja kontrola użytkownika może być świadoma, kiedy okno rodzica jest zamykane i odpowiednio działać!
źródło
Myślę, że rozładowanie nazywa się wszystko, ale ciężko istnieje w 4.7. Ale jeśli bawisz się starszymi wersjami .Net, spróbuj zrobić to w swojej metodzie ładowania:
Nie sądzę, aby starsze wersje rozładowały się, dopóki ładowanie nie zostanie obsłużone. Po prostu publikuję, ponieważ widzę, że inni nadal zadają to pytanie i nie widziałem tego proponowanego jako rozwiązania. Dotykam .Net tylko kilka razy w roku i wpadałem na to kilka lat temu. Ale zastanawiam się, czy jest to tak proste, jak nie wywoływanie wyładowania przed zakończeniem ładowania. Wydaje się, że to działa dla mnie, ale znowu w nowszej .Net wydaje się, że zawsze wywołuje unload, nawet jeśli ładowanie nie jest oznaczone jako obsługiwane.
źródło
UserControl ma Destructor, dlaczego tego nie użyjesz?
źródło