2010-05-14 11 views
6

Tengo un problema con la modalidad de los formularios bajo C# .NET. Digamos que tengo el formulario principal # 0 (ver la imagen a continuación). Este formulario representa el formulario de solicitud principal, donde el usuario puede realizar varias operaciones. Sin embargo, de vez en cuando, existe la necesidad de abrir una forma no modal adicional para realizar tareas de soporte de la funcionalidad de la aplicación principal adicional. Digamos que esta es la forma n. ° 1 en la imagen. En este formulario n. ° 1, podrían abrirse unos pocos formularios modales superpuestos (formulario n. ° 2 en la imagen) y, al final, un cuadro de diálogo de progreso que muestra un progreso y estado de operación largos, que podría tomar desde pocos minutos hasta algunas horas. El problema es que la forma principal # 0 no responde hasta que cierra todas las formas modales (# 2 en la imagen). Necesito que el formulario principal # 0 sea operativo en esta situación. Sin embargo, si abre un formulario no modal en el formulario n.º 2, puede operar tanto con el formulario modal n.º 2 como con el formulario no modal recién creado. Necesito el mismo comportamiento entre el formulario principal # 0 y el formulario # 1 con todas sus formas secundarias. ¿Es posible? ¿O estoy haciendo algo mal? Tal vez hay algún tipo de solución, realmente no me gustaría cambiar todo ShowDialog llama a Show ...Programación de WinForms - Problema modal y no modal de formularios

Image http://img225.imageshack.us/img225/1075/modalnonmodalproblem.png

+2

¿Está solicitando crear un formulario que solo sea modal a uno de sus otros formularios? – SLaks

+0

Quiero que el formulario principal # 0 permanezca receptivo cuando se abra un formulario no modal # 1 con algunos formularios secundarios modales adicionales (# 2). – Povilas

Respuesta

12

Los formularios modales hacen exactamente lo que significa "modal", deshabilitan todas las demás ventanas en la aplicación. Eso es bastante importante, su programa se encuentra en un estado algo peligroso. Tienes un trozo de código que está esperando a que se cierre el diálogo. Cosas realmente malas podrían suceder si esas otras ventanas no estuvieran deshabilitadas. Al igual que el usuario podría iniciar el cuadro de diálogo modal nuevamente, ahora su código está anidado dos veces. O podría cerrar la ventana de propietario del diálogo, ahora desaparece de repente.

Estos son exactamente el tipo de problemas con los que se encontraría si llama a Application.DoEvents() dentro de un bucle. Que es una forma de obtener un formulario para comportarse de manera modal sin deshabilitar otras ventanas. Por ejemplo:

Form2 mDialog; 

    private void button1_Click(object sender, EventArgs e) { 
     mDialog = new Form2(); 
     mDialog.FormClosed += (o, ea) => mDialog = null; 
     mDialog.Show(this); 
     while (mDialog != null) Application.DoEvents(); 
    } 

Esto es peligroso .

Sin duda es mejor utilizar formularios modales de la manera en que fueron diseñados para evitar problemas. Si no quiere un formulario modal, simplemente no lo haga modal, use el método Show(). Suscribirse a su evento FormClosing saber que está a punto de cerrar:

private void button1_Click(object sender, EventArgs e) { 
     var frm = new Form2(); 
     frm.FormClosing += new FormClosingEventHandler(frm_FormClosing); 
     frm.Show(); 
    } 

    void frm_FormClosing(object sender, FormClosingEventArgs e) { 
     var frm = sender as Form2; 
     // Do something with <frm> 
     //... 
    } 
+0

Gracias por su respuesta, creo que puedo usar un hilo de GUI separado, porque el formulario principal # 0 y el formulario # 1 básicamente viven sus propias vidas y no interactúan entre sí. Formulario # 1 podría ser incluso una aplicación por separado. No puedo cambiar ShowDialog() a Show() porque necesito formularios modales pero solo en el contexto de la forma # 1. El usuario no puede continuar con el formulario n.º 1 (solo con el formulario n.º 1) hasta que el formulario modal abierto desde el formulario n.º 1 no se cierre. – Povilas

3

La primera cosa que viene a la mente sería algo como esto. Puede deshabilitar el formulario 1 cuando inicia el formulario 2 y luego hacer que el formulario 1 maneje el evento cerrado del segundo formulario para volver a habilitarse. NO abriría el modal 2 usando el cuadro de diálogo Mostrar.

Ahora, tenga en cuenta que, desde el punto de vista del usuario, esto va a ser bastante engorroso, puede ver una aplicación MDI para obtener todas las ventanas dentro de un solo contenedor.

0

Su formulario principal no responderá hasta que se cierren todos los cuadros de diálogo modales que están en el mismo espacio de proceso. No hay trabajo para eso.

0

A mi me parece que te vendría bien una aplicación MDI Ajuste de la fórmula # 0 IsMdiContainer propiedad en true.

Entonces, se podría hacer algo por igual:

public partial class Form0 { 
    public Form0 { 
     InitializeComponent(); 
     this.IsMdiContainer = true; // This will allow the Form #0 to be responsive while other forms are opened. 
    } 

    private void button1_Click(object sender, EventArgs e) { 
     Form1 newForm1 = new Form1(); 
     newForm1.Parent = this; 
     newForm1.Show(); 
    } 
} 

Utilizando el ShowDialog() como ha afirmado en su pregunta hará que todas las formas Modal = true.

Por definición, una forma modal es:

Cuando se muestra una forma modal, sin entrada (teclado o un clic del ratón) puede ocurrir con excepción de los objetos en el formulario modal. El programa debe ocultar o cerrar un formulario modal (generalmente en respuesta a alguna acción del usuario) antes de que se produzca la entrada a otro formulario. Los formularios que se muestran de forma modal se utilizan normalmente como cuadros de diálogo en una aplicación.

Puede usar esta propiedad [(Modal)] para determinar si un formulario que ha obtenido de un método o propiedad se ha mostrado de forma modal.

Por lo tanto, un formulario modal se utilizará solo cuando requiera asistencia/interacción inmediata del usuario. El uso de formularios modales de otra manera hace creer que quizás estás corriendo en una dirección equivocada.

Si no quiere que su formulario principal sea un contenedor MDI, quizás usar el multihilo es una solución a través de una simple clase BackgroundWorker que es la clave de lo que desea lograr. Por lo tanto, me parece un olor diseño ...

  • ¿Qué es lo que quiere hacer, aparte de hacer que su principal forma de respuesta, etc.
  • ¿Qué es lo que tiene que hacer ?

Explicando lo que tiene que hacer, es posible que podamos guiarlo por completo en la dirección correcta, o al menos tal vez mejor.

+0

Gracias por su respuesta, intentaré explicar mejor. MDI o cambiar ShowDialog() a Show() no me resolverá esto, porque necesito formularios modales (editores de datos personalizados) y el usuario no puede continuar hasta que no haya terminado con el actual, pero necesito modalidad para trabajar solo en el contexto de la forma # 1. En el formulario # 1, los usuarios están trabajando con algunos datos que luego se necesitan en el formulario principal # 0. Básicamente, la forma principal # 0 y la forma # 1 viven sus propias vidas, y la forma # 1 podría ser incluso una aplicación separada. Desde # 0 se toman datos de algunos objetos singleton, donde el formulario # 1 está actualizando los datos. – Povilas

+0

Durante la mitad del año, todo estuvo bien, pero debido a la llegada de nuevos requisitos, tengo la situación en la que trabajar con un editor de datos personalizado podría tomar algunas horas. Así que creo que puedo usar lo que sugiere Hans Passant: un hilo de GUI por separado. Y sincronice datos a través de pocos objetos únicos. – Povilas

-1

En realidad, la respuesta es muy simple. Pruebe

newForm.showDialog(); 

Esto abrirá un formulario nuevo, mientras que el principal no se puede acceder.