2010-11-14 17 views
7

En WPF puede llamar al ShowDialog en una ventana exactamente una vez. Después de eso está hecho para.Cómo detectar que una ventana ha agotado su llamada "ShowDialog"

Me parece un poco cojo, pero esas son las reglas. Si llama ShowDialog de nuevo a obtener esta excepción:

No se puede establecer la visibilidad o llame Show, ShowDialog o WindowInteropHelper.EnsureHandle después de una ventana se ha cerrado

Lo que yo quiero saber es: ¿Cómo puedo tome un Window (o UserControl realmente) y verifique si se ha llamado al ShowDialog (así sé new hasta uno diferente antes de llamar al ShowDialog nuevamente).

Algo como esto:

public void ShowListOfClients() 
{ 
    // | This is the method I want to write 
    // V           
    RefreshViewIfNeeded(_myWindowOrUserControlThatShowsAList); 

    FillWindowWithBusinessData(_myWindowOrUserControlThatShowsAList); 
    _myWindowOrUserControlThatShowsAList.ShowDialog(); 

} 

NOTA: Es evidente que en el ejemplo anterior sería más fácil simplemente crear una nueva WindowOrUserControlThatShowsAList cada vez que entro en el método. Pero por favor considere la pregunta más que el ejemplo simplificado.

Respuesta

9

Esto no es exclusivo de ShowDialog(), Show() también. Y no, no hay propiedad IsDisposed para verificar. IsLoaded es solo la mitad de una solución, también será falso para la primera invocación.

primer enfoque es hacer sólo un cuadro de diálogo que puede ser re-muestra:

public bool CloseAllowed { get; set; } 

    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { 
     if (!CloseAllowed) { 
      this.Visibility = System.Windows.Visibility.Hidden; 
      e.Cancel = true; 
     } 
    } 

El siguiente es mantener explícitamente un seguimiento de la salud de la referencia del objeto:

private Window1 win = new Window1(); // say 

    private void button1_Click(object sender, RoutedEventArgs e) { 
     if (win == null) { 
      win = new Window1(); 
      win.Closing += delegate { win = null; }; 
     } 
     win.ShowDialog(); 
    } 
+0

Perdí el último. No puedo pensar en una // solución. –

+0

Me gusta el delegado al método de cierre. Eso se ve bien. ¡Gracias! – Vaccano

+0

Excepto que la primera sugerencia anterior específicamente no funciona para ventanas modales, es decir, con 'ShowDialog()'. Evitará la excepción, pero causa otros problemas, como no poder salir del proceso, y no mostrar la ventana correctamente la segunda vez que se hace visible. Solo la segunda sugerencia (es decir, siempre recreando la ventana) es viable. –

3

Bueno, la manera sucia de hacerlo sería atrapar la excepción.

La forma limpia de hacerlo sería mostrar una ventana con ShowDialog, y destruir (perder la referencia a, etc.) la ventana cuando la función retorna. La vista no debe estar estrechamente unida a los modelos (¿está utilizando MVVM, verdad?) Por lo que la creación de nuevos objetos visuales para cada vista de cliente no debería ser un problema.

+0

Estoy usando MVVM, pero si hago lo que sugiere luego hago que mi Modelo cree la vista que soporta (algo que me han dicho que MVVM frunce el ceño). – Vaccano

+0

Si un modelo necesita actualizarse en la pantalla, debe desencadenar un evento. Este evento se puede adjuntar a una vista. Esta vista puede ser la ventana del propietario, que dirige la visualización real a un cuadro de diálogo separado. – Guy

0

Fácil forma de lidiar con este problema sin estropear el evento de cierre:

public partial class MainWindow 
{ 
    private SomeCustomWindow _someCustomWindow; 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void OnOpenCustomWindowButtonClick(object sender, RoutedEventArgs e) 
    { 
     if (_someCustomWindow != null) 
      _someCustomWindow.Close(); 
     _someCustomWindow = new SomeCustomWindow(); 

     _someCustomWindow.ShowDialog(); 
    } 

    private void OnWindowClosing(object sender, CancelEventArgs e) 
    { 
     if (_someCustomWindow!= null) 
      _someCustomWindow.Close(); 
    } 
} 
Cuestiones relacionadas