2010-06-18 31 views
37

¿Es posible cerrar un formulario mientras el constructor se está ejecutando (o simplemente para detenerlo mostrando en esta etapa)?C# Cerrar un formulario durante un constructor

Tengo el siguiente código:

public partial class MyForm : Form 
{   
    public MyForm() 
    { 
     if (MyFunc()) 
     { 
      this.Close(); 
     } 
    } 
} 

que arroja un ObjectDisposedException en main(), aquí:

static void Main() 
    {    
     ... 

     // Following line errors 
     Application.Run(new MyForm()); 
    } 

he tratado de comprobar el resultado de MiFormulario así:

static void Main() 
{    
    ... 

    MyForm frm = new MyForm(); 
    if (frm != null) 
    { 
     // Following line errors 
     Application.Run(frm); 
    } 
} 

Pero eso no parece ayudar. ¿Alguien puede decirme una forma de evitar esto, por favor? ¿Tal vez una forma de verificar el formulario para ver si todavía existe?

+0

¿Qué excepción obtienes? –

Respuesta

66

Calling Close desde el constructor de la forma no es posible, como se llamará Dispose en un formulario que aún no se ha creado. Para cerrar el formulario después de la construcción, asignar un controlador de eventos anónimo al Load event que cierra su formulario antes de que se muestra por primera vez:

public partial class MyForm : Form 
{ 
    public MyForm() 
    { 
     if (ShouldClose()) 
     { 
      Load += (s, e) => Close(); 
      return; 
     } 

     // ... 
    } 

    // ... 
} 
+8

+1, simplemente reemplace Se muestra con Cargar para que no parpadee y usted tiene un ganador – Dialecticus

+0

@Dialecticus: Gracias. ¡Hecho! – Christian

+0

Esto me da este error: "Value Close() no se puede llamar al hacer CreateHandle()" – GuidoG

2

Su formulario no se abrirá desde el constructor. ¿Qué estás intentando lograr?

Si cierra este formulario, la ruta del código se cerrará completamente, dejándole sin ningún beneficio obvio (es decir, se cerrará Application.Run). Alguien más publicó un código sobre cómo ocultar el formulario, parece más probable.

4

¿Puedes hacer que MyFunc sea estático? y luego hacer algo como:

static void Main() 
{    
    ... 
    if (MyForm.MyFunc()) 
    { 
     Application.Run(new MyForm()); 
    } 
} 

esta esencia lo que daría el mismo control sobre si el formulario se va a construirse o no?

9

Cuando llama a Close() en un formulario, internamente está desechando el formulario y liberando los recursos administrados. Cuando hace esto:

Application.Run(new MyForm()); 

Es probable que obtenga una ObjectDisposedException. Lo que hay que hacer es configurar la visibilidad de la forma a través de una propiedad:

Application.Run(new MyForm() { Visible = false }); 

Sólo asegúrese de eliminar la llamada a close() en el constructor, o incluso mover la asignación de propiedad allí también.

20

Lo único que podría hacer es establecer un indicador para cerrarlo en el constructor y luego cerrarlo en el evento Shown. Por supuesto, si estás haciendo eso, tiene sentido mover el código para determinar si debería estar cerrado allí en primer lugar.

18

las siguientes obras: así

public partial class MyForm : Form 
{   
    public MyForm() 
    { 
     if (MyFunc()) 
     { 
      this.Shown += new EventHandler(MyForm_CloseOnStart); 
     } 
    } 

    private void MyForm_CloseOnStart(object sender, EventArgs e) 
    { 
     this.Close(); 
    } 
} 
4

me encontré con la adición de un controlador para el evento 'Carga' es mejor ya que esto forma en que el diálogo nunca se muestra en absoluto. Con el evento 'muestra' se pueden ver brevemente el diálogo de apertura y cierre que puede ser confuso:

public partial class MyForm : Form 
{   
    public MyForm() 
    { 
     if (MyFunc()) 
     { 
      this.Load += MyForm_CloseOnStart; 
     } 
    } 

    private void MyForm_CloseOnStart(object sender, EventArgs e) 
    { 
     this.Close(); 
    } 
} 
1

creo que no es aconsejable para cerrar un formulario en el constructor.Si hace esto, los usuarios de su formulario no sabrían si mostrar o no ShowDialog.

El siguiente código sería el uso normal:

// in the parent form: 
public void ShowMyForm() 
{ 
    MyForm form = new MyForm(); 
    form.propertyA = ...; 
    from.propertyB = ...; 
    DialogResult dlgResult = form.ShowDialog(this); 
    ProcessDialogResult(dlgResult); 
} 

que tendrá que añadir un código especial para decidir si ShowDialog y si desea procesar el resultado de diálogo.

Además, ¿está seguro de que las propiedades nunca influirán en si se debe mostrar el formulario o no? ¿También después de cambios futuros?

Durante la construcción, el formulario aún no se muestra/abre. Entonces me temo que Close() no hace lo que esperas.

El método perfecto es hacer sus verificaciones en Form_Load. Agregue el controlador de eventos de carga de formulario y realice sus comprobaciones en ese momento. Use la propiedad DialogResult para indicar que decidió no mostrar el formulario.

private void FormMain_Load (object sender, EventArgs e) 
{ 
    if (FormShouldNotLoad()) 
    { 
     this.DialogResult = System.Windows.Forms.DialogResult.Cancel; 
     Close(); 
    } 
} 

El usuario del código podría comprobar el resultado del diálogo:

// in the parent form: 
public void ShowMyForm() 
{ 
    MyForm form = new MyForm(); 
    form.propertyA = ...; 
    from.propertyB = ...; 
    DialogResult dlgResult = form.ShowDialog(this); 
    switch (dlgResult) 
    { 
     case System.Windows.Forms.DialogResult.Cancel: 
      ... 
      break; 
     case System.Windows.Forms.DialogResult.OK: 
      ... 
      break; 
     // etc. 
    } 
} 

Sin embargo, esto no va a funcionar, porque Cerrar sólo puede ser llamado correctamente Después de cargar. Por lo tanto, en lugar de llamar a Cerrar(), debe iniciar la función Cerrar() para llamar a la función Cerrar después de completar la carga:

El código para llamar a Cerrar() después de cargarse será como sigue:

private void FormMain_Load (object sender, EventArgs e) 
{ 
    if (MyFunc()) 
    { 
     CancelLoading(); 
    } 
} 

private delegate void InvokeDelegate(); 

private void CancelLoading() 
{ // will cancel loading this form 
    this.DialogResult = System.Windows.Forms.DialogResult.Cancel; 
    this.BeginInvoke(new InvokeDelegate(CloseThisForm)); 
} 

private void CloseThisForm() 
{ 
    this.Close(); 
} 

Lo bueno es que durante OnFormClosing y OnFormClosed usted sabe exactamente el estado del formulario: está completamente cargado, por lo que sabe qué hacer al cerrar.

+0

Esta debería ser la respuesta aceptada, la respuesta actualmente aceptada se compila pero da un error de tiempo de ejecución. – GuidoG

1

Si desea que su ventana para nunca será visto
(sin ventanas parpadeantes que se abren por un instante y luego desaparecen):

public new void Show() 
{ 
    if (MyFunc()) 
     base.Show(); 
    else 
     ; // dispose or whatever 
} 

Aunque Show(...) tiene 2 sobrecargas y ShowDialog(...) tiene 2 también.
No funciona para el formulario principal que se abre a través del Application.Run(). Pero, ¿quién haría eso de todos modos? Excepto que también hay una forma de abrir el formulario principal sin usar Application.Run().

Cuestiones relacionadas