domingo, 17 de febrero de 2013

[Winform] Instanciar Form conociendo su nombre

 

Introducción


Conociendo solo el nombre del formulario se abra una instancia del mismo.

Para poder realizar esta acción es necesario conocer el nombre del form, pero también bajo que namespace se ubica.

image

por ejemplo para abrir el form de alta de cliente se identifica

SNAGHTML239b6cc

pero si otro form se encuentra dentro de una carpeta es necesario definir el namespace donde se encuentra

SNAGHTML23d2650

Uso de Reflection


Para poder abrirlo vamos a necesitara Reflection el cual no permitirá descubrir el Type del form basado en la unión del namespace + nombre

es por eso que se define:

using System.Reflection;

 

private void btnAbrirForm_Click(object sender, EventArgs e)
{
    Assembly asm = Assembly.GetEntryAssembly();
    Type formtype = asm.GetType(string.Format("{0}.{1}", txtNamespace.Text, txtNombreForm.Text));

    Form f = (Form)Activator.CreateInstance(formtype);
    f.Show();
}

Se toma el assembly donde se encuentran los formularios y se obtiene el tipo, con el cual se creara la instancia dinámicamente

Código


[C#]
 

8 comentarios:

  1. Buenos dias Leandro,

    Interesante tu post y está relacionado con lo que necesito hacer. Acabo de crear un Treeview el cual utilizo de Menu Principal (eso ya esta hecho) y luego uso reflection para poder invocar cada formulario segun el nodo que seleccione y el tipo de formulario que sea



    Public Function ObtenerTipoFormulario(ByVal node As TreeNode) As Integer
    Dim TipoFormulario As Integer
    Using cn As New OleDbConnection(ConfigurationManager.ConnectionStrings("App").ToString())
    cn.Open()
    Dim cmd As New OleDbCommand("SELECT TipoFormulario FROM MENU WHERE IdentificadorPadre=@Nodo", cn)
    cmd.Parameters.Add("@Nodo", OleDbType.[Integer]).Value = node.Tag
    TipoFormulario = Convert.ToInt32(cmd.ExecuteScalar())
    Return TipoFormulario
    End Using
    End Function

    private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
    {
    TreeNode childNode = e.Node;
    string ChildName = e.Node.Text.ToString();
    if (childNode.Level != 0)
    {
    try
    {
    int PIntFormulario = ObtenerTipoFormulario(childNode);
    Assembly asm = Assembly.GetEntryAssembly();
    if (asm != null)
    {
    asm = Assembly.GetCallingAssembly();
    }
    switch (PIntFormulario)
    {
    case 1:
    Type formtype = asm.GetType("WindowsApplication1." + "FrmMante" + ChildName);
    Form frm = (Form)Activator.CreateInstance(formtype, true);
    frm.TopLevel = false;
    frm.BringToFront();
    frm.Show();
    frm.Text = "Formulario" + " " + e.Node.Text;
    frm.Dock = DockStyle.Fill;
    break;
    case 2:
    formtype = asm.GetType("WindowsApplication1." + "FrmVisor" + ChildName);
    frm = (Form)Activator.CreateInstance(formtype, true);
    frm.TopLevel = false;
    frm.BringToFront();
    frm.Show();
    frm.Text = "Formulario" + " " + e.Node.Text;
    frm.Dock = DockStyle.Fill;
    break;
    case 3:
    formtype = asm.GetType("WindowsApplication1." + "FrmRepor" + ChildName);
    frm = (Form)Activator.CreateInstance(formtype, true);
    frm.TopLevel = false;
    frm.BringToFront();
    frm.Show();
    frm.Text = "Formulario" + " " + e.Node.Text;
    frm.Dock = DockStyle.Fill;
    break;
    case 4:
    formtype = asm.GetType("WindowsApplication1." + "FrmOper" + ChildName);
    frm = (Form)Activator.CreateInstance(formtype, true);
    frm.TopLevel = false;
    frm.BringToFront();
    frm.Show();
    frm.Text = "Formulario" + " " + e.Node.Text;
    frm.Dock = DockStyle.Fill;
    break;
    }
    }
    catch (Exception t)
    {
    MessageBox.Show(t.Message);
    }
    }
    }

    El problema es principal es que siempre recibo el error: Value Cannot be null. Cuando he puesto un punto de interrupción sobre el evento doble click el valor del formtype=null, mientras que en .net realizo el mismo ejercicio y si funciona.

    Alguna idea de que podrá estar pasando?

    Saludos

    ResponderEliminar
  2. hola alexander

    no entendi porque comentas que en .net haces el mismo ejercicio y funciona, digo cuando pones el breakpoint tambien estas en .net

    podrias probar de usar el Assembly.GetExecutingAssembly() en lugar del GetEntryAssembly()

    ademas valida el string que se forma cuando usas el asm.GetType() estas seguro que el ChildName es valido ?

    saludos

    ResponderEliminar
  3. Hola Que tal excelente ejemplo, me has aclarado algunas dudas que tenia, me parece bien y ya lo pude adaptar con una lista de una base de datos, excelente para otorgar permisos de manera sencilla

    Gracias

    ResponderEliminar
  4. Y si no se conoce el nombre del formulario, se puede obtener de alguna manera y almacenarlo en una variable?

    Saludos.

    ResponderEliminar
    Respuestas
    1. hola
      Si estas dentro del propio form podrias usar la propiedad Name para tener el nombre.
      O sino usando Reflection. Un form no es mas que una clase por eso podrias obtener el nombre
      saludos

      Eliminar
  5. Eres la mera tos con flema como decimos en Guatemala, agradezco tu existencia.
    Hago énfasis a que no es la primera vez que salvas el pellejo.
    Saludos.

    ResponderEliminar
  6. Muy buena tu explicacion, ahora como podria enviar parametros abriendo el formulario de esa manera??

    ResponderEliminar