2008-12-19 42 views
44

Estoy trabajando en una aplicación que muestra algunas ventanas secundarias que el usuario puede cerrar o cerrar automáticamente. Mientras depuraba algunas excepciones que se lanzaban, descubrí que estaba tratando de llamar a métodos como Hide() en una ventana que ya se había cerrado; esta rama de código en particular era común en ambos casos y no me había dado cuenta de esto.¿Cómo se puede saber si una ventana de WPF está cerrada?

Una de mis primeras ideas fue buscar una propiedad en Window que indicara que la ventana se había cerrado. Parece que no puedo encontrar uno. En WinForms, buscaría en la propiedad IsDisposed un indicador confiable de que el formulario se había cerrado (no funcionará de manera confiable para un diálogo pero no estoy trabajando con diálogos). No veo nada equivalente en Window. La documentación para Window.Close() no parece indicar ninguna propiedad que el método modifique. ¿Me falta algo obvio, o es el único método para saber si se ha cerrado una ventana para manejar el evento Closed? Parece una exigencia estricta para una tarea simple.

Respuesta

45

De acuerdo con this conversation en los foros de MSDN WPF (consulte la última publicación), puede verificar si IsLoaded es falso, lo que significa que la ventana es "elegible" para descargar su contenido. ¡Espero que eso funcione para usted!

+4

Esta propiedad no se puede acceder desde otro hilo, y la invocación de una llamada al bloque luna dispuesta infinitamente. Así que terminé usando mi propia variable de instancia para eso y accedí a ella de una manera que no requiere sincronización (isClosed = true al principio del método OnClosed, luego lo leí más tarde nuevamente). – ygoe

+3

Esto no funciona si los eventos aún se están procesando.Por ejemplo, si un botón Click handler cierra una ventana y luego abre otra y la inicialización de la segunda ventana comprueba 'IsLoaded' de la primera, devolverá' true'. – nmclean

7

Otra forma: Application.Windows contiene una lista de ventanas abiertas. Puede verificar si esta colección contiene su ventana (se elimina después del cierre).

Parece que tiene que llamar al OfType<Window>() porque es una colección especializada.

+3

tenga cuidado con este - esto a veces puede contener ventanas que no están cerradas, especialmente aquellos que fallaron durante la visualización inicial debido a XAML malo –

3

Hope esto es útil para usted:

PresentationSource.FromVisual (ventana) == null;

+1

no funcionó para mí – user230910

3

No sé por qué el IsDisposed propiedad es interna, pero si no teme la reflexión:

var window = new Window(); 
var propertyInfo = typeof(Window).GetProperty("IsDisposed", BindingFlags.NonPublic | BindingFlags.Instance); 
var isDisposed = (bool)propertyInfo.GetValue(window); 

Dicho esto, la reflexión no es para ser usado en exceso, porque ya no estás protegido por la API pública de la clase. Asegúrese de usar al menos pruebas unitarias si va por esa ruta.

4

Mi solución fue simplemente conectar un evento para Closed caso del diálogo:

MikesDialog dlg = new MikesDialog(); 
dlg.Closed += delegate 
{ 
    // The user has closed our dialog. 
    validationgDlg = null; 
}; 

// ...elsewhere in the code... 

if (validationgDlg != null) 
{ 
    // Our "MikesDialog" is still open... 
    . . . 
} 
4

Si usted deriva de la clase Window, usted puede hacer esto:

public bool IsClosed { get; private set; } 

protected override void OnClosed(EventArgs e) 
{ 
    base.OnClosed(e); 
    IsClosed = true; 
} 

Tiene una ventaja sobre registrarse para el evento Cerrado, sin necesidad de anular el registro de la devolución de llamada.

0

Usted puede agregar una propiedad para no estática a la WindowClass bool IsClosed, y establecer cierto en el caso Closed:

public partial class MyWindow : Window 
{ 
    public bool IsClosed { get; set; } = false; 
    public MyWindow() 
    { 
     Closed += MyWindow_Closed; 
     InitializeComponent(); 
    } 
}  

private void MyWindow_Closed(object sender, EventArgs e) 
{ 
    IsClosed = true; 
} 
Cuestiones relacionadas