Carlos Mattos

Abrindo Formulários Dinamicamente C# (Windows Forms)

Introdução

Uma tarefa comum no desenvolvimento de soluções Windows Forms é a necessidade de instanciar formulários com base no nome da classe, ou seja, como o desenvolvedor pode abrir um formulário dinamicamente (programaticamente) passando o nome deste formulário (classe) como string. Isto é muito comum quando há necessidade de criarmos menus populados dinamicamente a partir de uma base de dados.  

Problema

Apesar de representar uma necessidade comum em aplicações Windows Forms, ainda há muitas dúvidas entre os desenvolvedores de como implementar corretamente um procedimento para instanciar um formulário dinamicamente. Faltam exemplos sobre esse tipo prática e os que estão disponíveis na Web não são facilmente encontrados e na maioria das vezes são apresentados em outro idioma.

 Solução

Uma construção simples com o método CreateInstance do objeto Activator permite implementar esta funcionalidade. Veja o código abaixo:

 public static void OpenForm(string Namespace_FormName, bool System_Modal)

{

Type t = Type.GetType(Namespace_FormName);

if (t != null)

{

   System.Windows.Forms.Form f =

   (System.Windows.Forms.Form)Activator.CreateInstance(t);

   if (System_Modal)

      f.ShowDialog();

   else

   f.Show();

}

}

Instanciando um formulário implementado em outro assembly

Com uma construção semelhante, é possível iniciar um formulário implementado eu outro assembly. Basta modificar o código acima para incluir informações sobre o assembly externo. O exemplo abaixo mostra como iniciar um formulário (MDIChild) contido em outro assembly e centralizá-lo no MDI:

 privatevoid OpenChildFormFromExternalAssembly(

string Full_Namespace_Class,

string Root_Namespace,

string Assembly_Version,

string Assembly_Culture,

string Assembly_PublicKeyToken,

bool System_Modal)

{

Type t = Type.GetType(Full_Namespace_Class + "," + Root_Namespace

+ ", Version=" + Assembly_Version

+ ", Culture=" + Assembly_Culture

+ ", PublicKeyToken=" + Assembly_PublicKeyToken);

if (t != null)

{

   System.Windows.Forms.Form f =

   (System.Windows.Forms.Form)Activator.CreateInstance(t);

   f.MdiParent = this;

   int TopMargin = 0;

         int LeftMargin = 0;

   LeftMargin = ((this.Width - f.Width) / 2) + this.Left;

         TopMargin = ((this.Height - f.Height) / 2) + this.Top - 50;

   f.StartPosition = FormStartPosition.Manual;

         f.Top = TopMargin;

   f.Left = LeftMargin;

   if (System_Modal)

      f.ShowDialog();

   else

      f.Show();

}

}

 As linhas abaixo demonstram como invocar o procedimento acima passando os parâmetros necessários:

 OpenChildFormFromExternalAssembly(

"EIS.Presentation.frmTipoEis", // Namespace completo

"EIS", // Root Namespace

"1.0.0.0", // Assembly Version (AssemblyInfo.cs)

"neutral", // Cultura (Default=neutral)

"null", // PublicKeyToken (Default=null)

false

);

 

Comments

Mauricio said:

Essa classe é de autoria minha, ajuda bastante tbm:

using System;

using System.Collections.Generic;

using System.Text;

using System.Windows.Forms;

namespace OTICA.Sistema

{

   public static class Formularios

   {

       public static System.Collections.Generic.List<System.Windows.Forms.Form> forms = new List<System.Windows.Forms.Form>();

       /// <summary>

       /// Abre um formulário.

       /// </summary>

       /// <param name="frm">Nova instancia do formulario que deseja abrir, caso ja exista uma ele desconsidera e elimina da memoria. ex: new Form1()</param>

       /// <param name="mdi_frm">Formulário MDI. Recipiente. Caso não haja nenhum insira null. ex: frmPrincipal ou null</param>

       /// <param name="dialog">Se o formulário é Dialog ou não! Formulário que sobrepoem a aplicação.</param>

       public static void abrir(Form frm, System.Windows.Forms.Form mdi_frm, bool dialog){

           bool aberto = false;

           for (int i = 0; i < forms.Count; i++) {

               if (frm.Name == forms[i].Name)

               {

                   aberto = true;

                   forms[i].Show();

               }

           }

           if (!aberto) {

               if (mdi_frm != null) {

                   frm.MdiParent = mdi_frm;                        

               }

               forms.Add(frm);

               frm = forms[forms.Count - 1];

               if (dialog)

               {

                   frm.ShowDialog();

               }

               else {

                   frm.Show();

               }

               frm.Focus();

           }

       }

       /// <summary>

       /// Fecha um formulario. Elimina da memória.

       /// </summary>

       /// <param name="frm">Adicionar o metodo Formularios.fechar(this); no evento FormClosed do formulario em questao.</param>

       public static void fechar(System.Windows.Forms.Form frm) {

           for (int i = 0; i < forms.Count; i++) {

               if (frm.Name == forms[i].Name)

               {

                   //frm.Close();

                   forms[i].Dispose();

                   forms.RemoveAt(i);

                   frm = null;

               }

           }

       }

   }

}

# February 9, 2011 10:58 AM

Getulio Salasar said:

Ótimo artigo.

Gostei muito.

Voce poderia me ajudar como fazer para capturar os nomes de todos os forms de um projeto ?

Tentei usar Reflection, mas não retorna todos os formulários, somente alguns, e não sei o motivo.

Agradeço antecipadamente.

getulio.salasar@gmail.com

# January 21, 2012 3:11 PM
Leave a Comment

(required) 

(required) 

(optional)
 

(required) 

If you can't read this number refresh your screen
Enter the numbers above: