2008-10-31 17 views
11

El control WPF WindowsFormsHost hereda de IDisposable.¿Cuándo puedo disponer de un control WPF IDisposable, p. WindowsFormsHost?

Si tengo un árbol visual complejo de WPF que contiene algunos de los controles anteriores, ¿qué evento o método puedo usar para llamar ID durante el cierre?

+1

Cuando dice 'durante el cierre', ¿quiere decir que la aplicación se está cerrando? El control ya no es visible? ¿Se está cerrando un diálogo? –

+0

Me refiero al apagado de la aplicación, pero también me interesa el caso de cierre del diálogo. – morechilli

Respuesta

4

Edificio de la respuesta de Todd me ocurrió esta solución genérica para cualquier control de WPF que se aloja en una ventana y quieren de para garantizar la disposición cuando la ventana está cerrada.

(Obviamente si se puede evitar que herede de IDisposable hacer, pero a veces simplemente no puede)

Desechar se llama cuando la ventana del primer padre en la jerarquía está cerrado.

(Posible mejora - cambiar el manejo de utilizar el patrón débil evento)

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

Pregunta: ¿qué haces en el método de eliminación? –

+0

depende del control - normalmente no tiene nada, pero desafortunadamente hay casos especiales, vea mi comentario en su respuesta – morechilli

+2

Esto no funcionará para aquellos que están alojando WPF dentro de una aplicación de Windows Forms. Hay formas más compatibles de conectar alternativamente a los eventos de cierre de WinForms asociados para el formulario principal, pero como lo tiene, esto no sería suficiente para una biblioteca de control de WPF ampliamente reutilizable. Limpiar solo cuando la ventana principal está cerrada probablemente no sea exactamente lo que la mayoría de los desarrolladores querrían. En su lugar, probablemente sea más conveniente realizar una limpieza cuando la primera ventana/página del árbol esté fuera del alcance (no necesariamente cuando está cerrada). – jpierson

-1

No necesita disponer de controles al cerrar un formulario, la API lo hará automáticamente si el control está en el árbol visual del formulario (como elemento secundario del formulario u otro control en el formulario)

+0

Mi WFH es hija de otro control de WPF en un árbol que incluye la ventana principal de wpf. Eliminar en la WFH nunca se llama. – morechilli

+0

Cuando se llama a Dispose en la ventana principal de wpf, se eliminarán todos sus elementos secundarios (y así sucesivamente). Su control de WFH debe desecharse en ese momento sin ningún trabajo adicional de su parte. –

+4

Dado que ni la clase de aplicación wpf ni la clase de ventana wpf heredan de IDisposable lo que parece improbable, creo que wpf es inmune a la necesidad de disponer hasta que obtenga winforms. – morechilli

8

En el caso de cierre de la aplicación, no hay nada que deba hacer para deshacerse correctamente de WindowsFormsHost. Como se deriva de HwndHost, la eliminación se realiza cuando el Dispatcher se cierra. Si usa Reflector, verá que cuando HwndHost se inicializa crea un WeakEventDispatcherShutdown.

Si lo usa en un cuadro de diálogo, lo mejor que puedo sugerir es anular OnClosed y deshacerse de su Host, de lo contrario, HwndHost se mantendrá hasta que se cierre el Dispatcher.

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

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

     base.OnClosed(e); 
    } 
} 

Una manera simple de probar cuando se llama a disponer es derivar una clase personalizada de WindowsFormsHost y jugar con diferentes situaciones. Ponga un punto de quiebre en el desecho y vea cuándo se llama.

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

Thx suena bien.Por lo tanto, para un control de windowsformshost con la aplicación.De por vida puedo confiar en el enganche de hwdhost al evento de apagado del operador, para un diálogo podría escribir un enlace similar en mi control al evento cerrado de la ventana de diálogo y puedo copiar ambos patrones para un control genérico IDisposable. – morechilli

0

controles WPF no implementan la interfaz IDisposable, porque no tienen nada que disponer (Sin asas para limpiar, no hay memoria no administrada para liberar). Todo lo que necesita hacer es asegurarse de que no tiene ninguna referencia a los controles y el GC los limpiará. Por lo tanto, WPF emplea weak event patterns para garantizar que los controles se puedan recoger como basura. Este es el patrón que necesita implementar para garantizar la limpieza, no IDisposable.

+1

Normalmente está en lo cierto, aunque hay excepciones, por ejemplo, WindowsFormsHost es un control de WPF e implementa IDisposable. Tiene un hwnd para desechar ya que aloja controles de formas de ganar. – morechilli

+0

Si tiene algo que desechar, implemente IDisposable, si no lo hace, no lo haga. Pero no lo implemente hasta que lo haga. –

+0

Parece que el patrón de evento débil aún podría plantear un problema en situaciones en las que intercambias un control existente y quieres asegurarte de que todos los eventos en ese control anterior y desencadenados por ese control se desenganchen para que dejen de procesar eventos. En nuestros experimentos, parece que estos eventos continúan disparando. Calling Dispose se usa para cumplir con este propósito de limpieza de eventos también en WinForms. – jpierson

Cuestiones relacionadas