2009-08-13 15 views
14

ChildWindow es una ventana modal, pero no bloquea. ¿Hay alguna forma de bloquearlo? Básicamente quiero un método ShowDialog() que llame a ChildWindow.Show() pero que no regrese hasta que el usuario haya cerrado ChildWindow. Intenté usar Monitor.Enter() para bloquear después de ChildWindow.Show(), pero ChildWindow nunca se procesó y el navegador se colgó. ¿Alguien tiene alguna idea?Cómo hacer que ChildWindow bloquee

+0

Podría explicar lo que está tratando de lograr ? – Ray

+0

Solo una ventana de bloqueo modal simple similar a MessageBox.Show() o Form.ShowDialog() –

+0

He intentado todo y nunca encontré una solución. Estaba intentando hacer mi propio MessageBox.Incluso probé la sincronización, pero siempre está bloqueada. Me di por vencido después de leer que Tim Heuer dijo que no era posible tener Modal verdadero. – Paully

Respuesta

5

No puede hacer lo que está tratando de hacer en Silverlight. Cualquier cambio que realice en la interfaz de usuario se ejecutará en el hilo de la interfaz de usuario. Si bloquea el hilo de la interfaz de usuario, el usuario no puede interactuar con el navegador, por lo que no se puede realizar ninguna acción para desbloquear el hilo.

Si realmente desea crear una ventana de diálogo de bloqueo, la única manera de hacerlo es desde un subproceso que no sea UI. P.ej. se podría crear un método que se ve algo como:

private void ShowModalDialog() 
    { 
     AutoResetEvent waitHandle = new AutoResetEvent(false); 
     Dispatcher.BeginInvoke(() => 
     { 
      ChildWindow cw = new ChildWindow(); 
      cw.Content = "Modal Dialog"; 
      cw.Closed += (s, e) => waitHandle.Set(); 
      cw.Show(); 
     }); 
     waitHandle.WaitOne(); 
    } 

Este método se mostrará una ventana de diálogo y no volverá hasta que la ventana de diálogo se cierra. Pero este método solo se puede invocar desde un no UI-thread. Llamar desde el hilo de la interfaz de usuario provocará un interbloqueo (dado que el hilo de la interfaz de usuario está esperando un evento que solo puede iniciarse en el hilo de la interfaz de usuario).

Como alternativa, debe considerar hacer su lógica asincrónica en lugar de forzarla a ser sincrónica.

+0

Me gusta esta solución y parece que debería funcionar, pero dado que no se puede invocar en el hilo de la interfaz de usuario, no estoy seguro de poder usar esto (aunque no especifiqué eso en mi pregunta (ya que Ni siquiera lo pensé entonces)). De cualquier manera, gran solución. –

-1

Intenté crear un diálogo modal "de bloqueo", teniendo un control personalizado que tiene una alineación vertical y horizontal como estiramiento, y luego agregar eso como un elemento secundario del diseño del control actual.

p. Ej.

<Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
     <Rectangle Fill="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.3" /> 
    </Grid> 

y luego en el control personalizado

Utilities.UITools.MessageBox x = new Utilities.UITools.MessageBox(); 
x.SetError(e.Result); 
this.LayoutRoot.Children.Add(x); 

Dependiendo de lo que tiene que ser visualizado en el modal, que dinámicamente agregar controles a la distribución modal. Claramente, no es una solución elegante, pero al menos funciona.

+0

Eso lo haría modal de alguna manera, pero no parece que sea un bloqueo ya que no hay una llamada a función que se bloquee hasta que el usuario cierre el cuadro de mensaje. –

+0

Lo hice bloqueando al vincular un evento en el cuadro de mensaje. Por lo tanto, bloquea el resto del programa hasta que el evento se dispare – Johannes

3

Si desea realizar alguna acción en el cierre de la ventana de su hijo, use el siguiente código. Ocultar controles no deseados antes de invocar y muestran el cierre de la ventana secundaria, simple :)

ChildWindow cw = new ChildWindow(); 
cw.Closed += new EventHandler(cw_Closed); 
cw.Show(); 
0

Usted podría intentar siempre cancelar el evento de cierre y ajuste la DialogResult más tarde.

void ConfigTemplatePopup_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     if (tmpDialogResult != null || DialogResult == true) return; 
     tmpDialogResult = DialogResult; //this is a field 
     e.Cancel = true; 
     var myMessageBox = new WspMessageBox("Are you sure you want to close?", true); 
     myMessageBox.Closed += (s, e2) => 
            { 
             if (wspMessageBox.DialogResult == true) 
             { 
              DialogResult = tmpDialogResult; 
             }else 
             { 
              tmpDialogResult = null; 
             } 
            }; 
     myMessageBox.Show(); 
    } 
0

Usando async and await in Silverlight 5 puede crear fácilmente un Show método estático que puede estar bloqueando, como

public partial class MyDialog { 
    MyResultType result; 
    readonly AutoResetEvent waitHandle; 

    MyDialog() { 
    InitializeComponent(); 
    waitHandle = new AutoResetEvent(false); 
    } 

    public static Task<MyResultType> Show() { 
    var dialog = new MyDialog(); 
    dialog.Show(); 
    dialog.Closed += (s, e) => dialog.waitHandle.Set(); 
    return Task<MyResultType>.Factory.StartNew(() => { 
     dialog.waitHandle.WaitOne(); return dialog.result; }); 
    } 

    void OkButton_Click(object sender, RoutedEventArgs e) { 
     result = new MyResultType(); 
     // Initialize result... 

     Close(); 
    } 
} 

y llamar al diálogo como

public async void TestDialog() { 
    var result = await ConfirmBox.Show(); 

    // This code will be performed after the Dialog is closed. 
    // use result... 
} 
+0

-1 Me temo, porque este fragmento no compila. La salida de 'Tarea .Factory.StartNew()' no está disponible. Además, aunque esta respuesta introduce el patrón async/await en la mezcla, no resuelve el problema fundamental de que no se puede bloquear el hilo de UI sin congelar el navegador, por lo que este enfoque no ofrece ningún valor real más allá de la solución de Keith Mahoney. –

+0

Este fragmento es de mi proyecto de trabajo. Lo uso como una solución común para los diálogos. Para compilarlo, necesitará el "paquete de orientación asíncrono", que puede agregar a su proyecto usando el nuget. Por favor, lea el artículo usando el enlace en mi respuesta. –

Cuestiones relacionadas