Когда я могу установить IDisposable WPF-элемент управления, например. WindowsFormsHost?

Элемент управления WPF WindowsFormsHost наследует от IDisposable.

Если у меня есть сложное визуальное дерево WPF, содержащее некоторые из вышеперечисленных элементов управления, какое событие или метод можно использовать для вызова IDispose во время выключения?

Ответ 1

Создание из ответа Тодда. Я придумал это общее решение для любого элемента управления WPF, который размещен в окне и хочет гарантировать удаление, когда это окно закрыто.

(Очевидно, если вы можете избежать наследования от IDisposable, но иногда просто не можете)

Dispose вызывается, когда первое родительское окно в иерархии закрывается.

(Возможное улучшение - изменение обработки событий для использования слабого шаблона)

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

            ...

        }

        ...
    }

Ответ 2

В случае выключения приложения вам нечего делать, чтобы правильно утилизировать WindowsFormsHost. Так как он происходит от HwndHost, утилизация обрабатывается, когда диспетчер отключается. Если вы используете Reflector, вы увидите, что при инициализации HwndHost он создает WeakEventDispatcherShutdown.

Если вы используете его в диалоговом окне, лучшее, что я могу предложить, это переопределить OnClosed и удалить ваш хост, иначе HwndHost будет зависать до тех пор, пока Диспетчер не завершит работу.

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

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

        base.OnClosed(e);
    }
}

Простым способом тестирования при вызове dispose является выведение пользовательского класса из WindowsFormsHost и воспроизведение в разных ситуациях. Поместите точку останова в распоряжение и посмотрите, когда она вызвана.

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

Ответ 3

Элементы управления WPF не реализуют интерфейс IDisposable, потому что им нечего распоряжаться (никаких ручек для очистки, не освобожденной памяти). Все, что вам нужно сделать, это убедиться, что у вас нет ссылок на элементы управления, и GC очистит их.

Поэтому WPF использует слабые шаблоны событий, чтобы гарантировать, что элементы управления могут быть собраны в мусор. Это шаблон, который вам нужно реализовать, чтобы обеспечить очистку, а не IDisposable.

Ответ 4

Вам не нужно удалять элементы управления при закрытии формы, API будет делать это автоматически, если элемент управления находится в визуальном дереве формы (в виде дочернего элемента формы или другого элемента управления в форме)