Introducción
Determinar si un form ha sido abierto, evitando que una nueva instancia sea creada.
Validar instancia entorno SDI
Para validar la existencia de la instancia de un formulario se hará uso del Application.OpenForms, con este y la ayuda de linq podremos buscar la existencia del form abierto.
La selección de botón abrirá una instancia, pero las siguientes pulsaciones solo harán que el mismo form pase al frente.
private void btnAbrirFormclientes_Click(object sender, EventArgs e) { //se localiza el formulario buscandolo entre los forms abiertos Form frm = Application.OpenForms.Cast<Form>().FirstOrDefault(x => x is frmEdicionCliente); if (frm != null) { //si la instancia existe la pongo en primer plano frm.BringToFront(); return; } //sino existe la instancia se crea una nueva frm = new frmEdicionCliente(); frm.Show(); }
El truco esta en poder determinar la lista de forma abiertos
Validar instancia entorno MDI
En un entorno MDI la validación es similar solo cambia la propiedad usada para determinar la lista de forms abiertos
private void abrirFormClienteToolStripMenuItem_Click(object sender, EventArgs e) { //se localiza el formulario buscandolo entre los forms abiertos Form frm = this.MdiChildren.FirstOrDefault(x => x is frmEdicionCliente); if (frm != null) { //si la instancia existe la pongo en primer plano frm.BringToFront(); return; } //se abre el form de clientes frm = new frmEdicionCliente(); frm.MdiParent = this; frm.Show(); }
Código
Hola Leandro,gracias por tu tiempo, me sirvió mucho el método para abrir UN formulario MDI, private void abrirFormClienteToolStripMenuItem_Click(object sender, EventArgs e), como puedo hacerlo público? , y no tener que escribir el mismo código para todos los formularios a abrir, probé algo así como el siguiente código y no logro hacerlo funcionar :
ResponderEliminarLlamo al método abrirForm (“NombreFormulario”)
Public void abrirForm(Form nombreFormulario)
{
//se localiza el formulario buscandolo entre los forms abiertos
Form frm = this.MdiChildren.FirstOrDefault(x => x is nombreFormulario);
if (frm != null)
{
//si la instancia existe la pongo en primer plano
frm.BringToFront();
return;
}
//se abre el form
frm = new NombreFormulario();
frm.MdiParent = this;
frm.Show();
}
Una ayudita si es posible, Gracias.
hola CESAR
ResponderEliminarno evaluaste crear una clase form base para que hereden de ella los forms?
en la clase base podrias poner esta funcionalidad para usarla de todos los forms que hereden de este FormBase
saludos
Hola Leandro, no considere esa opción pero leyendo tus trabajos (muy buenos e ilustrativos, gracias) hice una mezcla de tus métodos y logre que funcione, te aclaro soy nuevo en esto y me gustaría saber tu opinión si mi solución está en el rango de "buenas prácticas", gracias.
ResponderEliminarpublic void AbrirForm(string nombreForm)
{
Form frm = this.MdiChildren.FirstOrDefault(x => x.Name == nombreForm);
if (frm != null)
{
frm.BringToFront();
return;
}
// Assembly asm = Assembly.GetEntryAssembly();
Assembly asm = Assembly.GetExecutingAssembly();
Type formtype = asm.GetType("Sistemas." + nombreForm);
Form f = (Form)Activator.CreateInstance(formtype);
f.MdiParent = this;
f.WindowState = FormWindowState.Maximized;
f.BringToFront();
f.Show();
}
Muy bien Cesar me ha servido tu Código solo hice unas Modificaciones, Solo que no entendí un poco sobre la instancia que creaste de Assembly me imagino para ejecutar código ensamblador
EliminarMuy bien Cesar me ha servido tu Código solo hice unas Modificaciones, Solo que no entendí un poco sobre la instancia que creaste de Assembly me imagino para ejecutar código ensamblador
Eliminarhola CESAR
ResponderEliminarSi parece estar correcto
Cuando no encuentra el form dentro de la coleccion instancia por el nombre y lo asigna como parte del mdi child, eso esta bien
saludos
Hola Leandro, muchas gracias por el código. Muchas veces leo cosas tuyas y nunca tuve la amabilidad de agradecerte.
ResponderEliminarTe hago una consulta, yo tengo un switch con todos los id de menú que traigo de la base, cómo debería hacer, le paso el formulario que corresponda en cada case como parámetro?
Ya lo pude resolver, muchas gracias!
ResponderEliminarHola, te agradezco mucho por la lógica y el código, que te vaya bien !
ResponderEliminarhoal muey bueno tu aporte me funciono bien hasta un punto donde quiero enviar al formulario que estoy validando el valor de una variable que el tiene declarada pero al inentar enviarsela usando tu codigo nunca me envia la infor hacia el formulario como podria hacer esto y siempre validar si el formulario esta o no abierto yo lo hago de esta forma y me funciona
ResponderEliminarfrm_agregar_abonados ventana = new frm_agregar_abonados();
ventana.accion = true;
ventana.MdiParent = this.MdiParent;
ventana.Show();
pero ahi no valido si el formuario esta abierto siempre me lo abre infinitamente quisiera poder hacer esto mismo pero usar tu codigo para validar que no me vuelva a abrir otra ventana si esta ya esta abierta
hola
Eliminarvalidar que el form este abierto lo realizas con la tecnica que explico en este mismo articulo, o sea validas las instancia de los forms abiertos antes de hacer el show() de una nueva instancia
ahora me llama la atencion lo que comentas de enviar informacion, pareciera que la propiedad deberia asignarse correctamente, sino podrias pasar el dato por medio del constructor usando la tecnica de este otro articulo
Comunicar Formularios
saludos
Hola Leandro... muy buena explicacion... como siempre sacando de un apuro...
ResponderEliminarMe funciono perfecto muchisimas gracias,ahora lo que yo quiero hacer es:
ResponderEliminarUna vez comprobada la instancia, actualizar algunos variables publicos que tengo en ese formulario pero al declararlo como tipo "Form" no me saldrian mis variables, tendria que declararlo como frmPrincipal frm = Application.OpenForms.Cast().FirstOrDefault(x => x is frmPrincipal); mi problema es como podria adecuarlo para cualquier formulario pues tendria que ingresar un parametro de tipo "frmPrincipal" en mi metodo... Espero me deje entender , llevo poco tiempo en c# :(
hola
EliminarPero en ese linq solo estas devolviendo como respuesta si es form es del tipo frmPrincipal por eso usas
FirstOrDefault(x => x is frmPrincipal)
que sentido tiene definirlo como form simple si el filtro devuelve un form concreto
Quizas para hacerlo generico podrias usar una interfaz, pero debes exponer propiedades no variables
podria ser
public interface IForm{
string Prop1 {get;set;}
}
y la usarias
IForm frm = Application.OpenForms.Cast<IForm>().FirstOrDefault(x => x is IForm);
if(frm!=null){
string valor = frm.Prop1;
}
de esta forma si el form implementa la interfaz podras obtenerlo y esto sera generico
saludos
Muchas gracias Leandro, me sirvio de mucho
ResponderEliminarBuen día.
ResponderEliminarComo seria esto en WPF?
Muchas gracias por su ayuda me sirvió de maravilla al igual que las de msdn.
ResponderEliminarHola Leandro,
ResponderEliminarMuy buen artículo, la solución para los que quieren abrir una sola instancia de un formulario.
Yo uso un formulario, pero abro varias instancias según el valor de un parámetro, o sea, quiere decir que ese formulario lo uso para dar mantenimiento a varias tablas y según el parámetro se habilitan algunos controles.
En este caso, yo abro la instancia para dar mantenimiento a la tabla alumnos, luego abro esa misma instancia para dar mantenimiento a la tabla profesores, así mismo para la tabla directivos. O sea tengo 3 botones y cada uno me abre la misma instancia, pero con características distintas, el problema es si presiono dos veces un botón, me abre dos veces la instancia pero con una sola característica, ¿como hago para evitar esa carga?
el código es esto:
En el botón Alumno:
private void btnAlumno_Click(object sender, EventArgs e)
{
clsModulo.nRolSujeto = 1;
clsModulo.sRolSujeto = "ALUMNO";
frmBusinessSubject frmAlumno = new frmBusinessSubject();
frmAlumno.Text = ".: Mantenimiento Alumnos :.";
frmAlumno.lblTitulo.Text = frmAlumno.Text;
frmAlumno.MdiParent = this;
frmAlumno.Show();
}
En el botón Docente:
private void btnDocente_Click(object sender, EventArgs e)
{
clsModulo.nRolSujeto = 2;
clsModulo.sRolSujeto = "DOCENTE";
frmBusinessSubject frmDocente = new frmBusinessSubject();
frmDocente.Text = ".: Mantenimiento Docentes :.";
frmDocente.lblTitulo.Text = frmDocente.Text;
frmDocente.MdiParent = this;
frmDocente.Show();
}
En el botón Directivo:
private void btnDirectivo_Click(object sender, EventArgs e)
{
clsModulo.nRolSujeto = 3;
clsModulo.sRolSujeto = "DIRECTIVO";
frmBusinessSubject frmDirectivo = new frmBusinessSubject();
frmDirectivo.Text = ".: Mantenimiento Directivo :.";
frmDirectivo.lblTitulo.Text = frmDirectivo.Text;
frmDirectivo.MdiParent = this;
frmDirectivo.Show();
}
es la misma instancia.
Este comentario ha sido eliminado por el autor.
ResponderEliminarMuchas Gracias.!
ResponderEliminar