WPF コントロールの WindowsFormsHost は、IDisposable を継承しています。
上記のコントロールのいくつかを含む複雑な WPF ビジュアル ツリーがある場合、シャットダウン中に IDispose を呼び出すためにどのイベントまたはメソッドを使用できますか?
WPF コントロールの WindowsFormsHost は、IDisposable を継承しています。
上記のコントロールのいくつかを含む複雑な WPF ビジュアル ツリーがある場合、シャットダウン中に IDispose を呼び出すためにどのイベントまたはメソッドを使用できますか?
アプリケーションのシャットダウンの場合、WindowsFormsHost を適切に破棄するために必要なことは何もありません。HwndHost から派生しているため、Dispatcher がシャットダウンされたときに破棄が処理されます。Reflector を使用すると、HwndHost が初期化されるときに WeakEventDispatcherShutdown が作成されることがわかります。
ダイアログで使用している場合は、OnClosed をオーバーライドしてホストを破棄することをお勧めします。そうしないと、Dispatcher がシャットダウンされるまで 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 からカスタム クラスを派生させ、さまざまな状況で試してみることです。dispose にブレーク ポイントを設定し、いつ呼び出されるかを確認します。
public class CustomWindowsFormsHost : WindowsFormsHost
{
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
Todd の回答から構築して、ウィンドウによってホストされ、そのウィンドウが閉じられたときに破棄を保証したい 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();
};
}
};
...
}
...
}
WPF コントロールは IDisposable インターフェイスを実装しません。これは、処分するものが何もないためです(クリーンアップするハンドルや解放するアンマネージ メモリがないため)。コントロールへの参照がないことを確認するだけで、GC によってそれらがクリーンアップされます。
そのため、WPF は弱いイベント パターンを使用して、コントロールを確実にガベージ コレクションできるようにします。これは、IDisposable ではなく、確実にクリーンアップするために実装する必要があるパターンです。
フォームを閉じるときにコントロールを破棄する必要はありません。コントロールがフォームのビジュアル ツリーにある場合 (フォームの子またはフォーム内の他のコントロールとして)、API が自動的に破棄します。