2010-06-21 17 views
10

En mi aplicación C# tengo un diálogo de opción que se puede abrir desde un comando de menú.¿Cómo puedo hacer un formulario de instancia única (no aplicación)?

Quiero asegurarme de que el cuadro de diálogo de opciones tenga solo una instancia (el usuario no puede abrir más de una ventana de opción en un momento dado) sin hacerlo modal.

Además, si el usuario ya tiene esta ventana abierta, y hace clic en el elemento del menú para abrirla nuevamente, la aplicación solo hace que el formulario ya visible se convierta en la ventana superior.

¿Alguien me puede indicar las instrucciones sobre cómo realizar estas tareas?

Muchas gracias.

Respuesta

6

Necesitará esta forma como propiedad

Form1 myForm = null; 
private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
{ 
    myForm = null; 
} 

private void ShowForm() 
{ 
    if (myForm != null) 
    { 
     myForm.BringToFront(); 
    } 
    else 
    { 
     myForm = new Form1; 
     myForm.Show(); 
    } 
} 
+0

Simplemente declare myForm como estático para que sea accesible por mis opciones desde el evento FormClosed (para hacer que myForm = null nuevamente). – RHaguiuda

17

Bueno, la forma más simple es tener un campo estático que almacena una referencia a la instancia única o nulo, y luego un método para recuperarlo o crear uno nuevo.

Tenga en cuenta que no es lo mismo que convertirlo en un singleton, porque supongo que si el formulario está cerrado, querrá crear una nueva instancia la próxima vez. (La alternativa - ocultarlo y de volver a usarlo - se muestra en la respuesta de STO.) Es posible que desee algo como esto:

public class OptionsDialog : Form 
{ 
    private static OptionsDialog openForm = null; 

    // No need for locking - you'll be doing all this on the UI thread... 
    public static OptionsDialog GetInstance() 
    { 
     if (openForm == null) 
     { 
      openForm = new OptionsDialog(); 
      openForm.FormClosed += delegate { openForm = null; }; 
     } 
     return openForm; 
    } 
} 

Es posible que desee realizar el método de realizar el "llevarlo a la parte delantera" pasos, así , por supuesto.

+0

Hola @Jon, ¿me puede dar un ejemplo, por favor? – RHaguiuda

+0

@RHaguiuda: ¿Qué quieres que no sea el código que he dado? –

+1

Hmm, puedo ver de dónde vino esa solicitud, esa no era la publicación original. Arma más rápida en el truco del oeste? –

2

puede usar un código como éste:

private MyDialogForm _FormInstance; 

public void ShowOptions() 
{ 
    if (_FormInstance == null) 
    { 
     _FormInstance = new MyDialogForm(); 
     _FormInstance.FormClosing += (s,e) => 
     { 
      e.Cancel = true; 
      _FormInstance.Hide(); 
     } 
     } 
    _FormInstance.Show(); 
} 
0

que se supone que tiene al menos dos formas. Un formulario, llámalo frmMain, te permite abrir frmOptions. En frmMain, agregar una variable de frmOptions tipo así:

public partial class frmMain : Form 
{ 
    private frmOptions optionsInstance = null; 
    ... 

En la rutina que se abre el cuadro de diálogo Opciones, añadir lo siguiente:

if (optionsInstance == null || !optionsInstance.Visible) 
{ 
    optionsInstance = new frmOptions(); 
    optionsInstance.Show(); 
} 

Cuando frmOptions cierra, optionsInstance no será nulo, por lo que es por qué compruebas si está visible antes de crear una instancia de frmOptions.

Si esto no funciona para usted, podría intentar con un mutex, pero eso probablemente sea excesivo.

10

Debe evitar que se cierre el formulario. Si no lo hace, el formulario será eliminado y quedará inutilizable. Usted puede hacer esto mediante la implementación del evento FormClosing:

protected override void OnFormClosing(FormClosingEventArgs e) { 
     if (e.CloseReason == CloseReason.UserClosing) { 
      this.Hide(); 
      e.Cancel = true; 
     } 
    } 

para que sea un producto único, simplemente no perder de vista el tiempo de vida de la forma en su clase principal forma:

frmOptions options; 

    private void btnShowOptions_Click(object sender, EventArgs e) { 
     if (options == null) { 
      options = new frmOptions(); 
      // To make absolutely sure: 
      options.FormClosed += (o, ea) => options = null; 
     } 
     else { 
      options.WindowState = FormWindowState.Normal; 
     } 
     options.Show(); 
    } 
+0

gracias por esta respuesta, ¿puedes explicar '(o, ea) =>' Sé que has vuelto a establecer el formulario como nulo, pero no entiendo esta sintaxis – meda

+2

Es una expresión lambda. Normalmente escribiría (remitente, e) => pero esos nombres ya están en uso. –

+0

Gracias por aclarar – meda

0

Basado en Jon Skeet's answer, Estoy usando el siguiente código para mostrar un formulario como un cuadro de diálogo modal.

 if (this.aboutForm == null) 
     { 
      this.aboutForm = new AboutForm(); 
      this.aboutForm.FormClosed += (sender2, e2) => { this.aboutForm = null; }; 
      this.aboutForm.ShowDialog(this); 
     } 
     else 
     { 
      this.aboutForm.Focus(); 
     } 

que tengo que hacer esto porque tengo un elemento de menú para mostrar la forma en Sobre el menú del formulario principal, y en el menú contextual del icono de notificación.Si abro el formulario Acerca de usando el menú del formulario principal, aún puedo abrir otra instancia utilizando el elemento del menú contextual del icono de notificación.

Cuestiones relacionadas