counter for tumblr
December 2011 - Artículos - El blog de Javier Torrecilla

December 2011 - Artículos

Anteriormente en el blog ya os había hablado de las Betas publicas que iba liberando Oracle (I,II y III).

Bueno, creo que después de que le hayan pitado los oidos, ayer 29 de diciembre Oracle ha hecho el lanzamiento de la (primera) versión final de su driver para trabajar con Entity Framework para Oracle.

Lista de Descargas:

- 32-bit ODAC with Oracle Developer Tools for Visual Studio (Necesario para 32 y 64 bits)

- 32-bit ODAC xcopy

- x64 ODAC installer and xcopy

 

Para ver la documentación, la podeis ver y descargar desde aquí.

 

Algunas novedades a destacar:

- Mejora en Mapeo de Datos

- Uso de WCF y OData

- Mejoras en los Binding a Cursores

 

Para el año nuevo prometo hacer una serie de post en el que hable más en profundidad de esta nueva versión.

Un saludo!!!

Publicado por Javier Torrecilla | 1 comment(s)
Archivado en: ,,

Introducción

Antes de comenzar a hablar del propio titulo, vamos a hacer un índice de los artículos publicados en la serie de extensibilidad:

Parte 1: Agregar elementos a un menú de VS

Parte 2: Obtener los tipos de Proyecto de VS

Parte 3: Agregar Un Proyecto Nuevo

Parte 4: Agregar Ficheros a un Proyecto

Parte 5: Agregar Referencias

Parte 6: Eliminando Datos

 

En este artículo vamos a ver como agregar código o modificar el texto existente en el documento activo.

Código

   1: string addingText = GetText();
   2: int position = GetPosition();
   3: var fichero = (EnvDTE.Document)_applicationObject.Solution.DTE.ActiveDocument;
   4: var sel = (fichero.Selection as EnvDTE.TextSelection);
   5: sel.GotoLine(position);
   6: sel.Text = addingText ;
   7: sel.NewLine(1);

En el ejemplo utilizo un objeto de tipo TextSelection para agregar el texto en la posición que yo indique a través del conjunto de métodos disponibles.

 

Espero que os sea de utilidad Saludos

Publicado por Javier Torrecilla | con no comments
Archivado en: ,,

Introducción

Continuando con la serie de extensibilidad de Visual Studio, en este artículo vamos a ver como eliminar algunas de las cosas que ya hemos visto como añadir a un proyecto / solución desde un addin en VS.

Código

Eliminar un Proyecto Existente

   1: var solution = (Solution2)_applicationObject.Solution;
   2: var project = GetProject(solution);
   3: solution.Remove(project);
   4:  

 

Eliminar un Fichero Existente

   1: var solution = (Solution2)_applicationObject.Solution;
   2: var project = GetProject(solution);
   3: var file = GetFile(project);
   4: file.Remove();

Eliminar una Referencia Existente

   1: var solution = (Solution2)_applicationObject.Solution;
   2: var project = GetProject(solution);
   3: var reference = GetReference(project);
   4: reference.Remove();

 

Un saludo y espero que os sea de utilidad!!

Publicado por Javier Torrecilla | 1 comment(s)
Archivado en: ,,

Introducción

Continuando con la serie de extensibilidad de Visual Studio, en este artículo vamos a ver como agregar una referencia a un proyecto existente.

Código

Partiendo de los código utilizados en ejemplos anteriores, vamos a agregar una nueva opción de menú y dentro del evento clic agregaremos el siguiente fragmento de código:

   1: string file = string.Empty;
   2:            using (OpenFileDialog opd = new OpenFileDialog())
   3:            {
   4:                opd.Filter = "DLL | (*.dll)";
   5:                if (opd.ShowDialog() == DialogResult.OK)
   6:                {
   7:                    file = opd.FileName;
   8:                    try
   9:                    {
  10:                        var solution = (Solution2)_applicationObject.Solution;
  11:                        var project = GetProject(solution);
  12:                        (project.Object as VSLangProj.VSProject).References.Add(file);
  13:                    }
  14:                    catch (Exception ex )
  15:                    {
  16:                        
  17:                        MessageBox.Show(String.Format("Sucedio un problema intentando agregar la DLL: {0}",ex.Message));
  18:                    }
  19:                    
  20:                }
  21:            }

En el método estamos haciendo una conversión del tipo Project(ENVDTE) a VSPRoject, y a continuación a través de la Colección References, agregamos la DLL indicada.

 

Un saludo y espero que os sea de utilidad.

Publicado por Javier Torrecilla | 1 comment(s)
Archivado en: ,,

Introducción

Es algo muy común en aplicaciones WEB, ver que cuando el usuario introduce valores en un formulario y pulsa aceptar, si ha introducido algún valor erróneo, le aparezcan los errores y los mensajes de error.

Normalmente, esto se realiza a través de decorar con atributos las propiedades de nuestras entidades de negocio, por ejemplo:

   1: public class Empleado
   2: {
   3:     [Required(ErrorMessage = "El nombre es un campo obligatorio.")]
   4:     [StringLength(100,ErrorMessage="La longitud máxima permitida es de 100 caracteres.")]
   5:     public string Nombre { get; set; }
   6: }

 

En el ejemplo, si en el formulario no se mete, valor en el campo nombre o se introduce un nombre superior a 100 letras, al pulsar sobre el botón “Enviar” (Por ejemplo), se volvería a cargar el formulario con el errores por el Parámetro ErrorMessage del atributo.

El conjunto de atributos de validación se encuentra en el espacio de nombres “System.ComponentModel.DataAnnotations”, que para poder utilizarlo en una aplicación WINFORMS, es necesario, agregarlo como referencia al proyecto.

Ejemplo

Para comenzar voy a definir 2 interfaces en las que voy a basar el ejemplo.

La primera la interfaz IValidable, la cual va a ser implementada por todas mis entidades:

   1: public interface IValidable
   2: {
   3:     bool IsValid { get; set; }
   4:     List<ValidationResult> ValidationErrors { get; set; }
   5: }

La segunda la interfaz IValidator, que va a definir el contrato de los posibles validadores de objetos:

   1: interface IValidator
   2:    {
   3:         Tuple<bool, List<ValidationResult>> ValidateObject(IValidable objToValidate);
   4:    }

Esta interfaz presenta un método estático que va a recibir un objeto que implemente la Interfaz IValidable y va a devolver un Tuple con valor booleano y una lista de ValidationResult.

A continuación vamos a ver un ejemplo de implementación de la interfaz IValidator (Utilizando un patrón Singleton):

   1: public sealed class Validator : IValidator
   2:     {
   3:         private Validator()
   4:         {
   5:  
   6:         }
   7:         private static Validator validator = new Validator();
   8:  
   9:         public static Tuple<bool, List<ValidationResult>> Validate(IValidable objToValidate)
  10:         {
  11:             if (validator==null)
  12:                 validator = new Validator();
  13:             return validator.ValidateObject(objToValidate);
  14:         }
  15:        
  16:         private Tuple<bool,List<ValidationResult>> ValidateObject(IValidable  objToValidate)
  17:         {
  18:            var results = new List<ValidationResult>();
  19:            var context = new ValidationContext(objToValidate,null,null);
  20:             var obj = System.ComponentModel.DataAnnotations.Validator.TryValidateObject(objToValidate, context, results, true);
  21:   
  22:             return new Tuple<bool,List<ValidationResult>>(obj,results);
  23:         }
  24:        
  25:     }

En el método ValidateObject, vamos a utilizar un objeto de tipo ValidationContext, para definir el contexto de validación de nuestro objeto IValidable, y a través del método TryValidateObject, vamos a obtener si existen o no errores y el listado de errores (si existen) que se han producido, para devolverlos al objeto que realiza la llamada.

Ahora vamos a ver una implementación de la interfaz IValidable:

   1: public class Empleado : IValidable 
   2:     {
   3:         [Required(ErrorMessage = "El nombre es un campo obligatorio.")]
   4:         [StringLength(100,ErrorMessage="La longitud máxima permitida es de 100 caracteres.")]
   5:         public string Nombre { get; set; }
   6:         #region Miembros de IValidable
   7:  
   8:         public bool IsValid
   9:         {
  10:             get {
  11:                 var validator = Validator.Validate(this);
  12:                 _ValidationErrors = validator.Item2;
  13:                 return validator.Item1;
  14:             }
  15:         }
  16:         private List<ValidationResult> _ValidationErrors;
  17:         public List<ValidationResult> ValidationErrors
  18:         {
  19:             get
  20:             {
  21:                 return _ValidationErrors;
  22:             }
  23:             private set
  24:             {
  25:                 _ValidationErrors = value;
  26:             }
  27:         }
  28:  
  29:         #endregion
  30:     }

Dentro de la propiedad IsValid, he introducido la invocación al objeto Validator para hacer las pertinentes validaciones y obtener el conjunto de errores en el caso de existir alguno.

Para ver un ejemplo de utilización:

   1: Empleado empleado = new Empleado();//Fallará
   2: if (!empleado.IsValid)
   3: {
   4:     foreach (var error in empleado.ValidationErrors)
   5:     {
   6:         MessageBox.Show(error.ErrorMessage);
   7:     }
   8: }
   9: Empleado empleadoOK = new Empleado { Nombre = "Javier" };//No falllará
  10: if (!empleadoOK.IsValid)
  11: {
  12:     foreach (var error in empleadoOK.ValidationErrors)
  13:     {
  14:         MessageBox.Show(error.ErrorMessage);
  15:     }
  16: }
  17: else
  18: {
  19:     MessageBox.Show("El empleado es válido.");
  20: }

NOTA: Existe una interfaz IValidatableObject que presenta un método Validate que realiza una función similar, pero he decido crear mi propia interfaz para establecer la propiedad IsValid.

Espero que os sea interesante y/o de utilidad.

 

Saludos

Publicado por Javier Torrecilla | con no comments
Archivado en: ,,

Introducción

El otro día navegando por los foros de MSDN me encontré una pregunta curiosa: Pasar de un ListView en modo Details a un HTML y viceversa. El viernes respondí a como pasar a HTML, y hoy al paso contrario. El tema está en VB, pero me ha parecido interesante y he decidido crear este artículo en C#.

Código

En primer lugar, me he creado un método extensor de la clase HtmlElement para que me devuelva un IEnumerable para buscar por un determinado Tag (ej: div, table…)

   1: public static class HtmlExtensions
   2:     {
   3:         public static IEnumerable<HtmlElement> GetByTagName(this HtmlElement element, string TagName)
   4:         {
   5:             return element.All.Cast<HtmlElement>().
   6:                                 Where(el=>el.TagName.ToUpper().Equals(TagName.ToUpper())).ToList();
   7:         }
   8:     }

Bien, por otro lado me he creado una clase para realizar toda la lógica del proceso de conversión:

   1: public class HtmlToDatatable
   2:     {
   3:         public static DataTable GetHtmlDataTable(string url, string tablename)
   4:         {
   5:          
   6:             return GetDataTable(url,tablename);
   7:         }
   8:         private static string ReadHtml(string url)
   9:         {
  10:             System.Net.WebClient client = new System.Net.WebClient();
  11:             return client.DownloadString(url);
  12:         }
  13:         private static HtmlDocument GetHtmlDocument(string url)
  14:         {
  15:             string htmlText = ReadHtml(url);
  16:             if (string.IsNullOrWhiteSpace(htmlText)) throw new Exception("No se ha leido texto html.");
  17:             using (WebBrowser browser = new WebBrowser())
  18:             {
  19:                 browser.DocumentText = htmlText;
  20:                 do
  21:                 {
  22:                     Application.DoEvents();
  23:                 } while (browser.ReadyState != WebBrowserReadyState.Complete);
  24:                 return browser.Document;
  25:             }
  26:         }
  27:         private static HtmlElement GetHtmlTable(HtmlDocument doc, string tablename)
  28:         {
  29:             return doc.GetElementById(tablename);
  30:         }
  31:         private static DataTable GetDataTable(string url, string tablename)
  32:         {
  33:             DataTable dt = new DataTable();
  34:             HtmlDocument doc = GetHtmlDocument(url);
  35:             if (doc == null) throw new Exception("No se ha obtenido el documento HTML.");
  36:             HtmlElement table = GetHtmlTable(doc, tablename);
  37:             if (table == null) throw new Exception("No se ha obtenido la tabla indicada.");
  38:             CreateColumns(table, dt);
  39:             CreateRows(table, dt);
  40:             return dt;
  41:         }
  42:  
  43:         private static void CreateRows(HtmlElement table, DataTable dt)
  44:         {
  45:             List<HtmlElement> rowCol = table.GetByTagName("TR").ToList();
  46:             DataRow row;
  47:             foreach (HtmlElement fila in rowCol)
  48:             {
  49:                 if  (fila.Parent.TagName != "THEAD")
  50:                 {
  51:                     row = dt.NewRow();
  52:                     List<HtmlElement> tdCol  = fila.GetByTagName("TD").ToList();
  53:  
  54:                     for(int counter  = 0 ; counter<=dt.Columns.Count - 1;counter++)
  55:                         row[counter] = tdCol[counter].InnerText;
  56:                     
  57:                     dt.Rows.Add(row);
  58:                 }
  59:             
  60:             }
  61:             
  62:  
  63:  
  64:         }
  65:         private static  void CreateColumns(HtmlElement table, DataTable dt)
  66:         {
  67:             HtmlElement header = table.GetByTagName("THEAD").FirstOrDefault();
  68:             HtmlElement firstRow = table.GetByTagName("TR").FirstOrDefault();
  69:             if (header == null)
  70:             {
  71:                 CreateHeaders(dt, firstRow);
  72:             }
  73:             else
  74:             {
  75:                 CreateHeaders(dt, header);
  76:                
  77:             }
  78:            
  79:             
  80:         }
  81:         private static void CreateHeaders(DataTable dt, HtmlElement headerElement)
  82:         {
  83:             foreach (HtmlElement element in headerElement.All)
  84:             {
  85:                 dt.Columns.Add(element.InnerText);
  86:             }
  87:         }
  88:     }

El proceso consistiría:

Dada una ruta URL a leer, y un elemento Table del mismo:

Leeremos el texto HTML.

Obtendremos el HtmlDocument a través de un WebBrowser.

Obtendremos el HtmlElement relativo a la tabla indicada.

Obtendremos filas y columnas para rellenar el DataTable.

Para utilizar el código:

   1: this.dataGridView1.DataSource = HtmlToDatatable.GetHtmlDataTable(String.Format(@"{0}\test.html", Application.StartupPath), "datos");

 

Espero que os sea de utilidad.

 

Saludos!

Publicado por Javier Torrecilla | con no comments
Archivado en: ,,

Desde este post, me gustaría hacer un resumen personal de lo que me ha dado 2011:

- En lo personal nació mi segundo Hijo, Izan, y he visto como, en general, mi vida familiar ha sido genial.

- He conocido a gente realmente interesante de nuestro mundillo, no os voy a nombrar para no olvidarme de ninguno, pero tengo que daros las gracias.

- En lo “geek” ha sido un año realmente interesante, desde que fui nombrado como MCC hasta que en octubre fui nombrado MVP, hasta la asistencia a las Community Days organizados por Microsoft en Málaga.

- También en lo geek, he aprendido muchas cosas, y he asistido a grandes charlas técnicas que me han abierto los ojos en muchos aspectos.

Por ello considero, que en lo personal y geek el año ha sido realmente bueno.

 

Por otro lado, me gustaría felicitar a todo el mundo estas Fiestas de Navidad y el próximo año 2012 que esperamos que sea todavía mejor que 2011, y que nos traiga cosas buenas.

 

Saludos

PD: Y se me olvidaba espero que de salud sea mejor que este 2011, que me ha tratado bastante mal .... :(

Introducción

Siguiendo con la serie de post de extensibilidad que he estado escribiendo, vamos a ver en este artículo como agregar ficheros a un proyecto existente.

Agregar Ficheros

En este apartado vamos a ver como agregar ficheros nuevos o ficheros ya existentes.

Ficheros Nuevos

Al igual que existen plantillas predefinidas para proyectos, podemos encontrar plantillas de tipos de elementos agregables a un proyecto.

Para poder explorar el conjunto de plantillas existentes, dentro del directorio de instalación de Visual Studio, encontraremos la carpeta ItemTemplates, con los distintos lenguajes, instalados para poder consultar sus elementos.

 

   1: var solution = (Solution2)_applicationObject.Solution;
   2: var project = (Project)solution.Projects.Item(GetProject());
   3: var template = solution.GetProjectItemTemplate("Class.zip", "CSharp");
   4: var temp = project.ProjectItems.AddFromTemplate(template, "MyNewClass.cs");

El fragmento de código anterior está incluido en el evento click de una opción de menú de nuestro Addin.

El objeto Solution2 dispone del método GetProjectItemTemplate, que a través del nombre de la plantilla y el lenguaje a utilizar, nos va a permitir obtener el nombre de la plantilla para su importación.

A través del método AddFromTemplate de la colección ProjectItems del proyecto seleccionado, vamos a definir la plantilla obtenida y asignaremos el nombre de nuestro nuevo fichero.

Ficheros existentes

Existen dos formas de agregar un fichero existente a un proyecto:

- Como una copia

- De forma vinculada

1) Como una copia:

Se creará una copia del fichero deseado en la carpeta del proyecto y se agregará al mismo.

Para realizar este proceso bastaría con ejecutar el siguiente fragmento de código:

   1: string file = string.Empty;
   2: using (OpenFileDialog opd = new OpenFileDialog())
   3: {
   4:     if (opd.ShowDialog() == DialogResult.OK)
   5:     {
   6:         file = opd.FileName;
   7:         var solution = (Solution2)_applicationObject.Solution;
   8:         var project = (Project)solution.Projects.Item(GetProject());
   9:         project.ProjectItems.AddFromFileCopy(file);
  10:     }
  11: }

A través del cuadro de Abrir Fichero (OpenFileDialog) vamos a elegir un fichero existente, y lo agregaremos como una copia al proyecto seleccionado a través del método AddFromFileCopy.

2) De forma vinculada:

La segunda forma de agregar un fichero existente a un proyecto es a través de un Vinculo. Visual Studio establecerá un vinculo al fichero existente sin copiarlo en el directorio del proyecto. Esto puede generar problemas si el fichero se mueve o se elimina, provocando que el enlace se pierda.

El código va a ser muy similar al anterior, con la salvedad que en lugar de utilizar el método AddFromFileCopy se va a utilizar el método AddFromFile.

 

   1: string file = string.Empty;
   2: using (OpenFileDialog opd = new OpenFileDialog())
   3: {
   4:     if (opd.ShowDialog() == DialogResult.OK)
   5:     {
   6:         file = opd.FileName;
   7:         var solution = (Solution2)_applicationObject.Solution;
   8:         var project = (Project)solution.Projects.Item(GetProject());
   9:         project.ProjectItems.AddFromFile(file);
  10:     }
  11: }

 

Espero que os sea de utilidad.

 

Saludos

Publicado por Javier Torrecilla | 1 comment(s)
Archivado en: ,,

Introducción

En un post anterior vimos como definir un nuevo elemento en el Menú contextual de la Solución dentro de Visual Studio, y en este otro Post, hemos visto como obtener las distintas plantillas de proyectos de Visual Studio según una determinada versión.

El objetivo del presente artículo, es indicar como agregar a una solución existente un Tipo de Proyecto dado, para ello partiendo del código de los dos artículos anteriores vamos a plantear una solución.

Agregando un nuevo Proyecto

Dentro del evento Click de nuestro elemento de Menú, vamos a agregar el siguiente bloque de código:

   1: var solution = (Solution2)_applicationObject.Solution;
   2:  
   3: var newProjectName = String.Format("DLL{0}", solution.Projects.Count + 1);
   4: var newProjectPath = String.Format(@"{0}\{1}",solution.FullName.Substring(0,solution.FullName.LastIndexOf(@"\")),newProjectName );
   5: var templateName = "ClassLibrary.zip";
   6: var template = solution.GetProjectTemplate(templateName , "CSharp");
   7: solution.AddFromTemplate(template, newProjectPath , newProjectName );

En el ejemplo, construyo de manera genérica el nombre del nuevo Proyecto llamandolo DLL + un contador que será el número de proyectos existentes en mi solución más 1.

Vamos a definir la ruta donde se va a almacenar el nuevo proyecto, el cual estará almacenado dentro del directorio de nuestra solución incluyendo el nombre de nuestro proyecto.

A continuación, obtendremos el nombre de la plantilla a partir del método GetProjectTemplate del objeto Solution2 que hemos definido.

Y por último a través del método AddFromTemplate definiremos el nuevo proyecto y se agregará a nuestra solución.

 

Espero que os sea de utilidad.

 

Saludos

Publicado por Javier Torrecilla | 1 comment(s)
Archivado en: ,,

Introducción

En mi anterior artículo explicaba la forma de agregar una nueva opción de menú a uno ya existente, dentro de un Addin para Visual Studio.

Siguiendo un poco con el tema de “extender” Visual Studio, vamos a ver como podemos obtener los distintos tipos de proyecto de una determinada versión de Visual Studio. (En el siguiente artículo, veremos como agregar un proyecto a una solución existente).

Código

Aunque he publicado el código en Code MSDN, me gustaría exponerlo aquí y explicarlo brevemente:

En primer lugar, será necesario que obtengamos el directorio donde se encuentra instalada la versión de Visual Studio que vamos a comprobar:

   1: private  void GetVSFolder()
   2: {
   3:     string VSVersion = VSVersions.GetVSVersion(Version);
   4:     string folder = String.Format("{0}{1}",RegistryPath,VSVersion);
   5:     InstallationFolder = Registry.GetValue(folder, "InstallDir", "").ToString();
   6: }

Dada una versión de Visual Studio, y la ruta de Registro de Windows “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\”, vamos a obtener el valor de la clave “Install Dir”, y la asignaremos a una propiedad de nuestra clase.

Dentro del código vamos a tener un enumerador de las distintas versiones de VS y un diccionario (Dictionary<string,string>) con la pareja versión y Nombre largo. La versión es el valor que vamos a utilizar para poder obtener el directorio de Instalación.

La clase va a contener una Propiedad de tipo Lista de cadenas (List<string>) que va a contener las distintas agrupaciones para los proyectos (WEB, CSharp, VisualBasic…). Para obtener dichos valores:

   1: private  void  GetProjectTypes()
   2:         {
   3:             if (String.IsNullOrWhiteSpace(InstallationFolder)) throw new Exception("El Directorio de Visual Studio no puede estar vacio.");
   4:             ProjectType = new List<string>();
   5:             foreach(var folder in System.IO.Directory.EnumerateDirectories(String.Format(@"{0}\ProjectTemplates",InstallationFolder)))
   6:             {
   7:                 if (!ProjectType.Contains(folder)) ProjectType.Add(folder);
   8:             }
   9:  
  10:         }

Para tratar las distintas plantillas, he definido una clase “ProjectTemplate”:

   1: public class ProjectTemplate
   2:    {
   3:        public string TemplateName { get; set; }
   4:        public string TemplatePath { get; set; }
   5:        public string ProjectType { get; set; }
   6:        public override string ToString()
   7:        {
   8:            return String.Format("{0} - {1}", ProjectType, TemplateName);
   9:        }
  10:    }

Y dentro de la clase una propiedad de tipo Lista (List<ProjectTemplate>), que rellenaremos de la siguiente manera:

   1: private void GetProjectTemplates()
   2:         {
   3:             if (String.IsNullOrWhiteSpace(InstallationFolder)) throw new Exception("El Directorio de Visual Studio no puede estar vacio.");
   4:             ProjectTemplates = new List<ProjectTemplate>();
   5:             
   6:             foreach (var file in System.IO.Directory.EnumerateFiles(String.Format(@"{0}\ProjectTemplates", InstallationFolder),"*"
   7:                                                                         ,System.IO.SearchOption.AllDirectories))
   8:             {
   9:                 var possition = file.IndexOf("ProjectTemplates")+17;
  10:                ProjectTemplates.Add( new ProjectTemplate { 
  11:                                             TemplatePath = file,
  12:                                             TemplateName = file.Substring(file.LastIndexOf(@"\")+1),
  13:                                             ProjectType = file.Substring(possition,file.IndexOf(@"\",possition)) 
  14:                                         }
  15:                                         ) ;
  16:  
  17:             }
  18:         }

 

Para utilizar este proyecto, bastaría con agregar la referencia a un nuevo proyecto, y para poder probarlo:

   1: VSInfo.VSInfo vs = new VSInfo.VSInfo(VSInfo.eVSVersions.VS2010);
   2:            foreach (var template in vs.ProjectTemplates)
   3:            {
   4:               Console.WriteLine(template.ToString());
   5:            }

 

Espero que os sea de utilidad.

 

Saludos

Publicado por Javier Torrecilla | 2 comment(s)
Archivado en: ,,

Introducción

En este post quiero explicar como agregar una nueva opción de menú propia a un menú de Visual Studio.

¿Por dónde empezar?

El primer paso para que podamos empezar a “extender” Visual Studio es realizar la descarga del último SDK disponible.

Una vez descargado e instalado, vamos a abrir Visual Studio, y generaremos un nuevo proyecto de tipo: Complemento de Visual Studio

 

image

Una vez pulsado Aceptar, va aparecer un asistente donde indicaremos el lenguaje que vamos a utilizar en nuestro AddIn, el nombre, donde se va a utilizar…

 

image image image  image

image

  Una vez finalizado el asistente, vamos a ver el tema de agregar una nueva opción a un menú.

Un objeto predefinido en la clase de inicio del AddIn va a ser _applicationObject, que va a ser del tipo DTE2.

Vamos a definir un método donde vamos a implementar la lógica de agregación del menú:

   1: private void CreateMyMenuOption(DTE2 _applicationObject)
   2:         {
   3:             if (_applicationObject == null) throw new ArgumentNullException("_applicationObject");;
   4:             CommandBar oCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["Solution"];
   5:  
   6:             CommandBarButton myMenu = (CommandBarButton)oCommandBar.Controls.Add(MsoControlType.msoControlButton, 
   7:                                      System.Reflection.Missing.Value, System.Reflection.Missing.Value, 1, true);
   8:             myMenu.Caption = "Mi Menu";
   9:             try
  10:             {
  11:                 oSubMenuItemHandler = (CommandBarEvents)_applicationObject.Events.get_CommandBarEvents(myMenu);
  12:                 oSubMenuItemHandler.Click += new _dispCommandBarControlEvents_ClickEventHandler(oSubMenuItemHandler_Click);
  13:             }
  14:             catch (Exception ex)
  15:             {
  16:                 ShowException(ex);
  17:             }
  18:         }

A través del objeto CommandBar, vamos a elegir el menú donde vamos a agregar la nueva opción que estamos creando.

Para obtener un listado de los menús disponible bastaría con recorrer la colección y obtener la propiedad Name:

   1: CommandBars commandBars = (CommandBars)_applicationObject.CommandBars;

Dentro del método defino un objeto del tipo CommandBarButton que agregaré a la colección de controles existentes en el menú seleccionado previamente.

En este objeto podremos definir un conjunto de propiedades como puede ser el Nombre que se visualizará, el ToolTip, la descripción…

Para asignarle un evento, vamos a utilizar una variable del tipo CommandBarEvents, y asignaremos su evento click:

   1: CommandBarEvents oSubMenuItemHandler;
   2: void oSubMenuItemHandler_Click(object CommandBarControl, ref bool Handled, ref bool CancelDefault)
   3:         {
   4:             MessageBox.Show("Me has pulsado!!!");
   5:         }

El menú de destino de está prueba va a ser el menú contextual de “Soluciones”.

Para probar nuestro nuevo menú, bastará con que pulsemos F5. Al hacerlo, se va a abrir una nueva instancia de Visual Studio. Dentro generaremos un nuevo proyecto de tipo Solución en Blanco, al pulsar con el botón secundario sobre la nueva solución, aparecerá la nueva opción de menú que hemos definido de forma funcional.

image

image

 

Espero que os sea de utilidad.

Saludos!

Publicado por Javier Torrecilla | 3 comment(s)
Archivado en: ,,