none
duda sobre System.ComponentModel.Composition RRS feed

  • Pregunta

  • Utilizando este ejemplo: https://social.msdn.microsoft.com/Forums/es-ES/14863bd6-06b6-45ef-897b-5b48eb2b9657/llamar-librerias-como-plugins?forum=vcses, se me ocurrio en el evento onclick de numeros en lugar de llamar un mensaje o ejecutar un formulario deseo agregar un control al formulario asi, me da sensacion de mejor integracion al programa...

    agrege un TabControl con un tabPage llamado principal. todo bien hasta ahi, ahora lo que quiero es lo siguiente:

    en la dll, tengo creado un componente ya puede ser un tabPage para agregar al tabControl cuando se ejecute el evento onclick... pero no tengo la menor idea de como hacerlo...

    se que puedo buscar el componente padre hasta llegar al formulario y a partir de ahi buscar el componente TabControl, pero como le paso el formulario??? o alguien me puede dar una idea y si lo agregan a este mismo ejemplo seria maravilloso.

    gracias.


    lunes, 14 de diciembre de 2020 23:27

Respuestas

  •   

    Hola a todos, aquí traigo una solución al problema que publique... sinceramente espero que colaboren en una mejor solución o notaciones.

    1-Creamos una app windows form llamada "pruebaUsoMEF".
    2-Agregamos un "ToolStrip" y a este un "toolStripDropDownButton1".
    3-Agregamos un "TabControl" y eliminamos el segundo "TabPage".
    vea imagen:

    ojo en este punto...
    3a-Ponemos a "TabControl" como "public" y "static".
    3b-Para lograr que el componente sea estático, yo fui al "Form1.Designer.cs" y modificar esta linea:

    public static System.Windows.Forms.TabControl tabControl1; 

    y agregarle el "static". Luego el editor te marca error en todas las lineas donde esta "tabControl1" y lo único que tenemos que hacer es eliminar el "this.".
    4-Agregamos una clase a este proyecto, la cual llame "Agregar_Mod.cs".
    5-Agregamos este código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    using System.ComponentModel.Composition.Hosting;
    using System.ComponentModel.Composition;
    using System.Windows.Forms;
    using System.IO;
    
    namespace pruebaUsoMEF
    {
        class Agregar_Mod
        {
            private CompositionContainer _Contenedor;
            private string dirMod = Path.Combine(Environment.CurrentDirectory, "modulos");
    
            [Import(typeof(IMenuAgregar))]
            public IMenuAgregar LosItems { set; get; }
            public Agregar_Mod()
            {
                var Catalogo = new AggregateCatalog();
                Catalogo.Catalogs.Add(new AssemblyCatalog(typeof(Agregar_Mod).Assembly));
                if (System.IO.Directory.Exists(dirMod))
                {
                    Catalogo.Catalogs.Add(new DirectoryCatalog(dirMod));
                }
    
                _Contenedor = new CompositionContainer(Catalogo);
                try
                {
                    this._Contenedor.ComposeParts(this);
                }
                catch (CompositionException elError)
                {
                    System.Windows.Forms.MessageBox.Show(
                        elError.ToString(), "Mensaje de error",
                        System.Windows.Forms.MessageBoxButtons.OK,
                        System.Windows.Forms.MessageBoxIcon.Error);
                    Environment.Exit(0);
                }
            }
        }
    
        public interface IMenuAgregar
        {
            ToolStripMenuItem ItemColeccion { get; }
        }
    
        
        [Export(typeof(IMenuAgregar))]
        class ExportacionItemColeccion : IMenuAgregar
        {
            [ImportMany]
            IEnumerable<Lazy<IExportacion_ItemColeccion_MenuAgregar, IExportacion_ItemColeccion_MenuAgregar_MetaData>> Coleccion { set; get; }
    
            public ToolStripMenuItem ItemColeccion
            {
                get
                {
                    ToolStripMenuItem Resul = new ToolStripMenuItem();
    
                    foreach (Lazy<IExportacion_ItemColeccion_MenuAgregar, IExportacion_ItemColeccion_MenuAgregar_MetaData> item in Coleccion)
                    {
                        if (item.Value.MenuItem_Exportacion.Count() > 1)
                        {
                            Resul.DropDownItems.AddRange(item.Value.MenuItem_Exportacion);
                        }
                        else
                        {
                            Resul.DropDownItems.Add(item.Value.MenuItem_Exportacion[0]);
                        }
                    }
    
                    return Resul;
                }
            }
        }
    
        public interface IExportacion_ItemColeccion_MenuAgregar_MetaData
        {
            string Nombre { get; }
        }
    
        public interface IExportacion_ItemColeccion_MenuAgregar
        {
            ToolStripDropDownItem[] MenuItem_Exportacion { get; }
        }
    }


    nota: es prescindible agregar las referencia de System.Drawing y System.ComponentModel.Composition, ademas de:

    using System.ComponentModel.Composition.Hosting; using System.ComponentModel.Composition; using System.Windows.Forms; using System.IO; 

    6-Ahora ya podemos hacer uso de la estructura para obtener los item del menu "Agregar", para eso agregamos en "Form1.cs" el siguiente código:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace pruebaUsoMEF
    {
        public partial class Form1 : Form
        {
            Agregar_Mod agregar_Mod;
            public Form1()
            {
                InitializeComponent();
    
                agregar_Mod = new Agregar_Mod();
                toolStripDropDownButton1.DropDown = agregar_Mod.LosItems.ItemColeccion.DropDown;
            }
        }
    }

    7-Creamos un nuevo proyectos de librería de clases, yo lo nombre "AgregarClassLibrary".
    ver código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    using System.ComponentModel.Composition;
    using System.Windows.Forms;
    
    namespace AgregarClassLibrary
    {
        [Export(typeof(pruebaUsoMEF.IExportacion_ItemColeccion_MenuAgregar))]
        [ExportMetadata("Nombre", "Tabpage")]
        class ItemsAgregar_Class : pruebaUsoMEF.IExportacion_ItemColeccion_MenuAgregar
        {
            public ToolStripDropDownItem[] MenuItem_Exportacion
            {
                get
                {
    
                    ToolStripDropDownItem[] Resul = new ToolStripDropDownItem[1];
                    // este constructor ya me permite pasarle el evento click
                    Resul[0] = new ToolStripMenuItem("Tab Page", null, new EventHandler(AgregarTabPage_Click));                
                    return Resul;
                }
            }
    
            private void AgregarTabPage_Click(object sender, EventArgs e)
            {
                pruebaUserControl userControl = new pruebaUserControl();
                TabPage tabPage = new TabPage("Prueba UserControl");
                tabPage.Name = "pUserControl";
                tabPage.Controls.Add(userControl);
                userControl.Dock = DockStyle.Fill;
                pruebaUsoMEF.Form1.tabControl1.TabPages.Add(tabPage);
                pruebaUsoMEF.Form1.tabControl1.SelectedTab=tabPage;
            }
        }
    }
    8-Aquí también tenemos que agregar las referencia de System.ComponentModel.Composition, ademas de:

    using System.ComponentModel.Composition;
    using System.Windows.Forms;

    9-Agregamos a este proyecto un control de usuario que llame "pruebaUserControl.cs".
    ver diseño:

    ver código:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace AgregarClassLibrary
    {
        public partial class pruebaUserControl : UserControl
        {
            public pruebaUserControl()
            {
                InitializeComponent();
            }
    
            private void Button2_Click(object sender, EventArgs e)
            {
                MessageBox.Show("Hola mundo");
            }
    
            private void Button1_Click(object sender, EventArgs e)
            {
                Control padre = this;
    
                do
                {
                    padre = padre.Parent;
                } while (padre.Name == "pUserControl");
    
                TabControl tabControl = (TabControl)padre;
                tabControl.TabPages.RemoveAt(tabControl.TabCount - 1);
            }
        }
    }

    10-Importante, en el apartado "Compilación" en las propiedades de este proyecto establecer la ruta de salida como muestra la siguiente imagen:

    Mis observaciones:
    No me parece muy seguro ni profesional declarar el tabControl1 como publico ni estático, si alguien puede colaborar a mejorar esto o al menos opinar si es seguro usar este tipo de implementación.

     
    • Marcado como respuesta EricRRModerator miércoles, 16 de diciembre de 2020 21:02
    miércoles, 16 de diciembre de 2020 20:05

Todas las respuestas

  • Hola,

    Gracias por levantar tu consulta en los foros de MSDN. Entendimos su pregunta y vamos a darle seguimiento para buscar la mejor repuesta pertinente al caso.

    Gracias por usar los foros de MSDN.

    Eric Ruiz

    ____________________________

    Por favor recuerde "Marcar como respuesta" las respuestas que hayan resuelto su problema, es una forma común de reconocer a aquellos que han ayudado, y hace que sea más fácil para los otros visitantes encontrar la solución más tarde.

    Si tiene algún cumplido o reclamo sobre el soporte de MSDN siéntase en la libertad de contactar MSDNFSF@microsoft.com.

    martes, 15 de diciembre de 2020 14:06
    Moderador
  •   

    Hola a todos, aquí traigo una solución al problema que publique... sinceramente espero que colaboren en una mejor solución o notaciones.

    1-Creamos una app windows form llamada "pruebaUsoMEF".
    2-Agregamos un "ToolStrip" y a este un "toolStripDropDownButton1".
    3-Agregamos un "TabControl" y eliminamos el segundo "TabPage".
    vea imagen:

    ojo en este punto...
    3a-Ponemos a "TabControl" como "public" y "static".
    3b-Para lograr que el componente sea estático, yo fui al "Form1.Designer.cs" y modificar esta linea:

    public static System.Windows.Forms.TabControl tabControl1; 

    y agregarle el "static". Luego el editor te marca error en todas las lineas donde esta "tabControl1" y lo único que tenemos que hacer es eliminar el "this.".
    4-Agregamos una clase a este proyecto, la cual llame "Agregar_Mod.cs".
    5-Agregamos este código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    using System.ComponentModel.Composition.Hosting;
    using System.ComponentModel.Composition;
    using System.Windows.Forms;
    using System.IO;
    
    namespace pruebaUsoMEF
    {
        class Agregar_Mod
        {
            private CompositionContainer _Contenedor;
            private string dirMod = Path.Combine(Environment.CurrentDirectory, "modulos");
    
            [Import(typeof(IMenuAgregar))]
            public IMenuAgregar LosItems { set; get; }
            public Agregar_Mod()
            {
                var Catalogo = new AggregateCatalog();
                Catalogo.Catalogs.Add(new AssemblyCatalog(typeof(Agregar_Mod).Assembly));
                if (System.IO.Directory.Exists(dirMod))
                {
                    Catalogo.Catalogs.Add(new DirectoryCatalog(dirMod));
                }
    
                _Contenedor = new CompositionContainer(Catalogo);
                try
                {
                    this._Contenedor.ComposeParts(this);
                }
                catch (CompositionException elError)
                {
                    System.Windows.Forms.MessageBox.Show(
                        elError.ToString(), "Mensaje de error",
                        System.Windows.Forms.MessageBoxButtons.OK,
                        System.Windows.Forms.MessageBoxIcon.Error);
                    Environment.Exit(0);
                }
            }
        }
    
        public interface IMenuAgregar
        {
            ToolStripMenuItem ItemColeccion { get; }
        }
    
        
        [Export(typeof(IMenuAgregar))]
        class ExportacionItemColeccion : IMenuAgregar
        {
            [ImportMany]
            IEnumerable<Lazy<IExportacion_ItemColeccion_MenuAgregar, IExportacion_ItemColeccion_MenuAgregar_MetaData>> Coleccion { set; get; }
    
            public ToolStripMenuItem ItemColeccion
            {
                get
                {
                    ToolStripMenuItem Resul = new ToolStripMenuItem();
    
                    foreach (Lazy<IExportacion_ItemColeccion_MenuAgregar, IExportacion_ItemColeccion_MenuAgregar_MetaData> item in Coleccion)
                    {
                        if (item.Value.MenuItem_Exportacion.Count() > 1)
                        {
                            Resul.DropDownItems.AddRange(item.Value.MenuItem_Exportacion);
                        }
                        else
                        {
                            Resul.DropDownItems.Add(item.Value.MenuItem_Exportacion[0]);
                        }
                    }
    
                    return Resul;
                }
            }
        }
    
        public interface IExportacion_ItemColeccion_MenuAgregar_MetaData
        {
            string Nombre { get; }
        }
    
        public interface IExportacion_ItemColeccion_MenuAgregar
        {
            ToolStripDropDownItem[] MenuItem_Exportacion { get; }
        }
    }


    nota: es prescindible agregar las referencia de System.Drawing y System.ComponentModel.Composition, ademas de:

    using System.ComponentModel.Composition.Hosting; using System.ComponentModel.Composition; using System.Windows.Forms; using System.IO; 

    6-Ahora ya podemos hacer uso de la estructura para obtener los item del menu "Agregar", para eso agregamos en "Form1.cs" el siguiente código:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace pruebaUsoMEF
    {
        public partial class Form1 : Form
        {
            Agregar_Mod agregar_Mod;
            public Form1()
            {
                InitializeComponent();
    
                agregar_Mod = new Agregar_Mod();
                toolStripDropDownButton1.DropDown = agregar_Mod.LosItems.ItemColeccion.DropDown;
            }
        }
    }

    7-Creamos un nuevo proyectos de librería de clases, yo lo nombre "AgregarClassLibrary".
    ver código:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    using System.ComponentModel.Composition;
    using System.Windows.Forms;
    
    namespace AgregarClassLibrary
    {
        [Export(typeof(pruebaUsoMEF.IExportacion_ItemColeccion_MenuAgregar))]
        [ExportMetadata("Nombre", "Tabpage")]
        class ItemsAgregar_Class : pruebaUsoMEF.IExportacion_ItemColeccion_MenuAgregar
        {
            public ToolStripDropDownItem[] MenuItem_Exportacion
            {
                get
                {
    
                    ToolStripDropDownItem[] Resul = new ToolStripDropDownItem[1];
                    // este constructor ya me permite pasarle el evento click
                    Resul[0] = new ToolStripMenuItem("Tab Page", null, new EventHandler(AgregarTabPage_Click));                
                    return Resul;
                }
            }
    
            private void AgregarTabPage_Click(object sender, EventArgs e)
            {
                pruebaUserControl userControl = new pruebaUserControl();
                TabPage tabPage = new TabPage("Prueba UserControl");
                tabPage.Name = "pUserControl";
                tabPage.Controls.Add(userControl);
                userControl.Dock = DockStyle.Fill;
                pruebaUsoMEF.Form1.tabControl1.TabPages.Add(tabPage);
                pruebaUsoMEF.Form1.tabControl1.SelectedTab=tabPage;
            }
        }
    }
    8-Aquí también tenemos que agregar las referencia de System.ComponentModel.Composition, ademas de:

    using System.ComponentModel.Composition;
    using System.Windows.Forms;

    9-Agregamos a este proyecto un control de usuario que llame "pruebaUserControl.cs".
    ver diseño:

    ver código:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace AgregarClassLibrary
    {
        public partial class pruebaUserControl : UserControl
        {
            public pruebaUserControl()
            {
                InitializeComponent();
            }
    
            private void Button2_Click(object sender, EventArgs e)
            {
                MessageBox.Show("Hola mundo");
            }
    
            private void Button1_Click(object sender, EventArgs e)
            {
                Control padre = this;
    
                do
                {
                    padre = padre.Parent;
                } while (padre.Name == "pUserControl");
    
                TabControl tabControl = (TabControl)padre;
                tabControl.TabPages.RemoveAt(tabControl.TabCount - 1);
            }
        }
    }

    10-Importante, en el apartado "Compilación" en las propiedades de este proyecto establecer la ruta de salida como muestra la siguiente imagen:

    Mis observaciones:
    No me parece muy seguro ni profesional declarar el tabControl1 como publico ni estático, si alguien puede colaborar a mejorar esto o al menos opinar si es seguro usar este tipo de implementación.

     
    • Marcado como respuesta EricRRModerator miércoles, 16 de diciembre de 2020 21:02
    miércoles, 16 de diciembre de 2020 20:05
  • Hola, 

    Muchas gracias por compartir la solución, esto será de ayuda para los usuarios de este.

    Saludos,

    Eric Ruiz

    miércoles, 16 de diciembre de 2020 21:02
    Moderador