Когда я могу использовать одноразовый элемент управления WPF, например WindowsFormsHost?

StackOverflow https://stackoverflow.com/questions/254271

  •  05-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение 2

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

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

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

            ...

        }

        ...
    }

Другие советы

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

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

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

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

        base.OnClosed(e);
    }
}

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top