Tutorial: Crear una extensión de proyecto de SharePoint
En este tutorial se muestra cómo crear una extensión para los proyectos de SharePoint.Puede utilizar una extensión de proyecto para responder a los eventos de nivel de proyecto como cuando se agrega, se elimina, o cambia un proyecto.También puede agregar propiedades personalizadas o responder cuando cambia un valor de propiedad.A diferencia de las extensiones de elemento de proyecto, las extensiones de proyecto no pueden estar asociadas a un tipo de proyecto de SharePoint determinado.Cuando crea una extensión de proyecto, se carga cuando se abre cualquier tipo de proyecto de SharePoint en Visual Studio.
En este tutorial, creará una propiedad booleana personalizada que se agrega a cualquier proyecto de SharePoint creado en Visual Studio.Cuando se establece en True, la nueva propiedad agrega o asigna una carpeta de recursos Images al proyecto.Cuando se establece en False, se quita la carpeta Images, si existe.Para obtener más información, vea Cómo: Agregar y quitar carpetas asignadas.
En este tutorial se muestran las siguientes tareas:
Crear una extensión Visual Studio para los proyectos SharePoint que hace lo siguiente:
Agrega una propiedad de proyecto personalizada a la ventana Propiedades.La propiedad se aplica a cualquier proyecto de SharePoint.
Utiliza el modelo de objetos de proyecto de SharePoint para agregar una carpeta asignada a un proyecto.
Usa el modelo de objetos de automatización (DTE) de Visual Studio para eliminar una carpeta asignada del proyecto.
Compilar un paquete de extensión (VSIX) de Visual Studio para implementar el ensamblado de la extensión de propiedad de proyecto.
Depurar y probar la propiedad de proyecto.
Requisitos previos
Necesitará los componentes siguientes en el equipo de desarrollo para completar este tutorial:
Ediciones compatibles de Microsoft Windows, SharePoint y Visual Studio.Para obtener más información, vea Requisitos para desarrollar soluciones de SharePoint.
Visual Studio SDK.En este tutorial se utiliza la plantilla Proyecto VSIX del SDK para crear un paquete VSIX para implementar la extensión de propiedad de proyecto.Para obtener más información, vea Extender la Herramientas de SharePoint en Visual Studio.
Crear los proyectos
Para completar este tutorial, debe crear dos proyectos:
Un proyecto VSIX para crear el paquete VSIX e implementar la extensión de proyecto.
Un proyecto de biblioteca de clases que implemente la extensión de proyecto.
Comience el tutorial creando ambos proyectos.
Para crear el proyecto VSIX
Inicie Visual Studio.
En la barra de menú, elija Archivo, Nuevo, Proyecto.
En el cuadro de diálogo Nuevo proyecto , expanda los nodos Visual c# o Visual Basic y, a continuación el nodo Extensibilidad .
[!NOTA]
Este nodo solo está disponible si instala Visual Studio SDK.Para obtener más información, vea la sección Requisitos previos, anteriormente en este tema.
En la parte superior del cuadro de diálogo, elija .NET Framework 4,5 en la lista de versiones de .NET Framework, y elija la plantilla Proyecto VSIX .
En el cuadro Nombre , escriba ProjectExtensionPackage, y elija el botón Aceptar .
El proyecto ProjectExtensionPackage aparece en Explorador de soluciones.
Para crear la extensión de proyecto
En Explorador de soluciones, abra el menú contextual para el nodo de la solución, elija Agregary, a continuación Nuevo proyecto.
[!NOTA]
En los proyectos Visual Basic , el nodo de la solución aparece en Explorador de soluciones únicamente si la casilla Mostrar solución siempre se selecciona en General, Projects and Solutions, Options Dialog Box.
En el cuadro de diálogo Nuevo proyecto , expanda los nodos Visual c# o Visual Basic y, a continuación Windows.
En la parte superior del cuadro de diálogo, elija .NET Framework 4,5 en la lista de versiones de .NET Framework, y elija la plantilla de proyecto Biblioteca de clases .
En el cuadro Nombre , escriba ProjectExtension, y elija el botón Aceptar .
Visual Studio agrega el proyecto ProjectExtension a la solución y abre el archivo de código predeterminado Class1.
Elimine el archivo de código Class1 del proyecto.
Configurar el proyecto
Antes de escribir el código que crea la extensión del elemento de proyecto, tiene que agregar los archivos de código y las referencias de ensamblado al proyecto de extensión.
Para configurar el proyecto
Agregue un archivo de código denominado CustomProperty al proyecto ProjectExtension.
Abrir el menú contextual para el proyecto ProjectExtension y, a continuación Agregar referencia.
En el cuadro de diálogo Administrador de referencia – CustomProperty , elija el nodo Framework , y seleccione la casilla junto a los ensamblados System.ComponentModel.Composition y System.Windows.Forms.
Elija el nodo Extensiones , active la casilla junto a los ensamblados Microsoft.VisualStudio.SharePoint y EnvDTE, y después elija el botón Aceptar .
En Explorador de soluciones, bajo la carpeta Referencias para el proyecto ProjectExtension , elija EnvDTE.
En la ventana Propiedades, cambie el valor de Incrustar tipos de interoperabilidad a False.
Definir la nueva propiedad de proyecto de SharePoint
Cree una clase que defina la extensión de proyecto y el comportamiento de la nueva propiedad.Para definir la nueva extensión de proyecto, la clase implementa la interfaz ISharePointProjectExtension.Implemente esta interfaz siempre que desee definir una extensión para un proyecto de SharePoint.También agregue ExportAttribute a la clase.Este atributo permite que Visual Studio detecte y cargue la implementación de ISharePointProjectExtension.Pase el tipo ISharePointProjectExtension al constructor del atributo.
Para definir la nueva propiedad de proyecto de SharePoint
Pegue el código siguiente en el archivo de código CustomProperty.
Imports System Imports System.Linq Imports System.ComponentModel Imports System.ComponentModel.Composition Imports System.Windows.Forms Imports Microsoft.VisualStudio.SharePoint Imports EnvDTE Namespace Contoso.SharePointProjectExtensions.MapImagesFolder ' Export attribute: Enables Visual Studio to discover and load this extension. ' MapImagesFolderProjectExtension class: Adds a new Map Images Folder property to any SharePoint project. <Export(GetType(ISharePointProjectExtension))> _ Public Class MapImagesFolderProjectExtension Implements ISharePointProjectExtension Public Sub Initialize(ByVal projectService As ISharePointProjectService) Implements ISharePointProjectExtension.Initialize AddHandler projectService.ProjectPropertiesRequested, AddressOf Me.projectService_ProjectPropertiesRequested End Sub Private Sub projectService_ProjectPropertiesRequested(ByVal sender As Object, ByVal e As SharePointProjectPropertiesRequestedEventArgs) Dim propertiesObject As CustomProjectProperties = Nothing ' If the properties object already exists, get it from the project's annotations. If False = e.Project.Annotations.TryGetValue(propertiesObject) Then ' Otherwise, create a new properties object and add it to the annotations. propertiesObject = New CustomProjectProperties(e.Project) e.Project.Annotations.Add(propertiesObject) End If e.PropertySources.Add(propertiesObject) End Sub End Class Public Class CustomProjectProperties Private sharePointProject As ISharePointProject = Nothing Private Const MapImagesFolderPropertyDefaultValue As Boolean = False Private Const MapImagesFolderPropertyId = "ContosoMapImagesFolderProperty" Public Sub New(ByVal myProject As ISharePointProject) sharePointProject = myProject End Sub ' Represents the new boolean property MapImagesFolder. ' True = Map an Images folder to the project if one does not already exist; otherwise, do nothing. ' False = Remove the Images folder from the project, if one exists; otherwise, do nothing. <DisplayName("Map Images Folder")> _ <DescriptionAttribute("Specifies whether an Images folder is mapped to the SharePoint project.")> _ <DefaultValue(MapImagesFolderPropertyDefaultValue)> _ Public Property MapImagesFolder As Boolean Get Dim propertyStringValue As String = String.Empty ' Try to get the current value from the .user file; if it does not yet exist, return a default value. If Not sharePointProject.ProjectUserFileData.TryGetValue(MapImagesFolderPropertyId, propertyStringValue) Then Return MapImagesFolderPropertyDefaultValue Else Return CBool(propertyStringValue) End If End Get Set(ByVal value As Boolean) If value Then If Not ImagesMappedFolderInProjectExists(sharePointProject) Then ' An Images folder is not mapped to the project, so map one. Dim mappedFolder As IMappedFolder = sharePointProject.MappedFolders.Add(MappedFolderType.Images) sharePointProject.ProjectService.Logger.WriteLine( _ mappedFolder.Name & " mapped folder added to the project.", LogCategory.Status) End If ElseIf (ImagesMappedFolderInProjectExists(sharePointProject) AndAlso UserSaysDeleteFile()) Then ' An Images folder is mapped to the project and the user wants to remove it. DeleteFolder() End If sharePointProject.ProjectUserFileData(MapImagesFolderPropertyId) = value.ToString() End Set End Property Private Function ImagesMappedFolderInProjectExists(ByVal sharePointProject As ISharePointProject) As Boolean Dim returnValue As Boolean = False For Each folder As IMappedFolder In sharePointProject.MappedFolders ' Check to see if an Images folder is already mapped. If (folder.FolderType = MappedFolderType.Images) Then returnValue = True End If Next Return returnValue End Function Private Function UserSaysDeleteFile() As Boolean ' Ask the user whether they want to delete the Images folder. Dim returnValue As Boolean = False If (MessageBox.Show("Do you want to delete the Images folder from the project?", _ "Delete the Images folder?", MessageBoxButtons.YesNo) = DialogResult.Yes) Then returnValue = True End If Return returnValue End Function Private Sub DeleteFolder() ' The Visual Studio DTE object model is required to delete the mapped folder. Dim dteProject As EnvDTE.Project = _ sharePointProject.ProjectService.Convert(Of ISharePointProject, EnvDTE.Project)(sharePointProject) Dim targetFolderName As String = _ sharePointProject.MappedFolders.First(Function(mf) mf.FolderType = MappedFolderType.Images).Name Dim mappedFolderItem As EnvDTE.ProjectItem = dteProject.ProjectItems.Item(targetFolderName) mappedFolderItem.Delete() sharePointProject.ProjectService.Logger.WriteLine("Mapped Folder " & _ targetFolderName & " deleted", LogCategory.Status) End Sub End Class End Namespace
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.ComponentModel.Composition; using System.Windows.Forms; using Microsoft.VisualStudio.SharePoint; using EnvDTE; // Adds a new property called MapImagesFolder to any SharePoint project. // When MapImagesFolder is set to true, the Image folder is mapped to the project. // When MapImagesFolder is set to false, the Image folder is deleted from the project. namespace SP_Project_Extension { // Export attribute: Enables Visual Studio to discover and load this extension. [Export(typeof(ISharePointProjectExtension))] // Defines a new custom project property that applies to any SharePoint project. public class SPProjectExtension : ISharePointProjectExtension { // Implements ISharePointProjectService.Initialize, which determines the behavior of the new property. public void Initialize(ISharePointProjectService projectService) { // Handle events for when a project property is changed. projectService.ProjectPropertiesRequested += new EventHandler<SharePointProjectPropertiesRequestedEventArgs>(projectService_ProjectPropertiesRequested); } void projectService_ProjectPropertiesRequested(object sender, SharePointProjectPropertiesRequestedEventArgs e) { // Add a new property to the SharePoint project. e.PropertySources.Add((object)new ImagesMappedFolderProperty(e.Project)); } } public class ImagesMappedFolderProperty { ISharePointProject sharePointProject = null; public ImagesMappedFolderProperty(ISharePointProject myProject) { sharePointProject = myProject; } static bool MapFolderSetting = false; [DisplayName("Map Images Folder")] [DescriptionAttribute("Specifies whether an Images folder is mapped to the SharePoint project.")] public bool MapImagesFolder // Represents the new boolean property MapImagesFolder. // True = Map an Images folder to the project if one does not already exist; otherwise, do nothing. // False = Remove the Images folder from the project, if one exists; otherwise, do nothing. { get { // Get the current property value. return MapFolderSetting; } set { if (value) { if (!ImagesMappedFolderInProjectExists(sharePointProject)) { // An Images folder is not mapped to the project, so map one. IMappedFolder mappedFolder1 = sharePointProject.MappedFolders.Add(MappedFolderType.Images); // Add a note to the logger that a mapped folder was added. sharePointProject.ProjectService.Logger.WriteLine("Mapped Folder added:" + mappedFolder1.Name, LogCategory.Status); } } else { if (ImagesMappedFolderInProjectExists(sharePointProject) && UserSaysDeleteFile()) { // An Images folder is mapped to the project and the user wants to remove it. // The Visual Studio DTE object model is required to delete the mapped folder. // Reference the Visual Studio DTE model, get handles for the SharePoint project and project items. EnvDTE.Project dteProject = sharePointProject.ProjectService.Convert<ISharePointProject, EnvDTE.Project>(sharePointProject); string targetFolderName = sharePointProject.MappedFolders.First(mf => mf.FolderType == MappedFolderType.Images).Name; EnvDTE.ProjectItem mappedFolderItem = dteProject.ProjectItems.Item(targetFolderName); mappedFolderItem.Delete(); sharePointProject.ProjectService.Logger.WriteLine("Mapped Folder " + targetFolderName + " deleted", LogCategory.Status); } } MapFolderSetting = value; } } private bool ImagesMappedFolderInProjectExists(ISharePointProject sharePointProject) { bool retVal = false; foreach (IMappedFolder folder in sharePointProject.MappedFolders) { // Check to see if an Images folder is already mapped. if (folder.FolderType == MappedFolderType.Images) retVal = true; } return retVal; } private bool UserSaysDeleteFile() { // Prompt the user whether they want to delete the Images folder. bool retVal = false; if (MessageBox.Show("Do you want to delete the Images folder from the project?", "Delete the Images folder?", MessageBoxButtons.YesNo) == DialogResult.Yes) { retVal = true; } return retVal; } } }
Compilar la solución
A continuación, compile la solución para asegurarse de que se compila sin errores.
Para compilar la solución
- En la barra de menú, elija Generar, Compilar solución.
Crear un paquete VSIX para implementar la extensión de propiedad de proyecto
Para implementar la extensión de proyecto, utilice el proyecto VSIX en la solución para crear un paquete VSIX.Primero, configure el paquete VSIX modificando el archivo source.extension.vsixmanifest incluido en el proyecto VSIX.A continuación, cree el paquete VSIX compilando la solución.
Para crear y configurar el paquete VSIX
En Explorador de soluciones, abra el menú contextual para el archivo source.extension.vsixmanifest, y después elija el botón Abrir .
Visual Studio abre el archivo en el diseñador de manifiestos.La información que aparece en la pestaña Metadatos también aparece en Extensiones y actualizaciones. Todos los paquetes VSIX requieren el archivo extension.vsixmanifest.Para obtener más información sobre este archivo, vea Referencia de esquema de extensión VSIX.
En el cuadro Nombre de producto , entre en Propiedad de proyecto personalizada.
En el cuadro Autor , entre en Contoso.
En el cuadro Descripción , escriba el Una propiedad de proyecto de SharePoint personalizada que alterna la asignación de la carpeta de recurso Images al proyecto.
Elija la ficha Activos , y elija el botón Nuevo .
El cuadro de diálogo Agregar nuevo activo aparece.
En la lista Tipo , elija Microsoft.VisualStudio.MefComponent.
[!NOTA]
Este valor corresponde al elemento MEFComponent del archivo extension.vsixmanifest.Este elemento especifica el nombre de un ensamblado de extensión en el paquete VSIX.Para obtener más información, vea MEFComponent Element.
En la lista Origen , elija el botón de opción Un proyecto de la solución actual .
En la lista Proyecto , elija ProjectExtension.
Este valor identifica el nombre del ensamblado que está compilando en el proyecto.
Elija Aceptar para cerrar el cuadro de diálogo Agregar nuevo activo .
En la barra de menú, elija Archivo, Guardar todos cuando termine, y luego cierre el diseñador de manifiestos.
En la barra de menú, elija Generar, Compilar solución, y asegúrese de que el proyecto se compila sin errores.
En Explorador de soluciones, abra el menú contextual para el proyecto ProjectExtensionPackage , y elija el botón Abrir carpeta en el Explorador de archivos .
En Explorador de archivos, abra la carpeta de salida de compilación de ProjectExtensionPackage, y después comprueba que la carpeta contiene un archivo ProjectExtensionPackage.vsix.
De forma predeterminada, la carpeta de resultado de compilación es ..\bin\Debug, que se encuentra bajo la carpeta que contiene el archivo de proyecto.
Probar la propiedad de proyecto
Ya puede probar la propiedad de proyecto personalizada.Es más fácil depurar y probar la nueva extensión de propiedad de proyecto en una instancia experimental Visual Studio.Esta instancia Visual Studio se crea cuando se ejecuta un VSIX u otro proyecto de extensibilidad.Después de depurar el proyecto, puede instalar la extensión en el sistema y continuar depurándola y probar en una instancia normal Visual Studio.
Para depurar y probar la extensión en una instancia experimental de Visual Studio
Reinicie Visual Studio con credenciales administrativas, y vuelva a abrir la solución ProjectExtensionPackage.
Inicie una compilación de depuración del proyecto o eligiendo la clave F5 o, en la barra de menús, eligiendo Depurar, Iniciar depuración.
Visual Studio instala la extensión a %UserProfile%\AppData\Local\Microsoft\VisualStudio\11.0Exp\Extensions\Contoso\Custom Project Property \ 1,0 e inicia una instancia experimental Visual Studio.
En la instancia experimental Visual Studio, cree un proyecto de SharePoint para una solución de granja, y use los valores predeterminados en los otros valores del asistente.
En la barra de menú, elija Archivo, Nuevo, Proyecto.
En la parte superior del cuadro de diálogo Nuevo proyecto , elija .NET Framework 3.5 en la lista de versiones de .NET Framework.
Las extensiones de herramientas de SharePoint requieren características de esta versión .NET Framework.
Bajo el nodo Plantillas , expanda el nodo Visual c# o Visual Basic , elija el nodo SharePoint y, a continuación el nodo 2010 .
Elija la plantilla Proyecto de SharePoint 2010 , y escriba en ModuleTest como el nombre del proyecto.
En Explorador de soluciones, elija el nodo del proyecto ModuleTest .
Una nueva propiedad Map Images Folder personalizado aparece en la ventana Propiedades con un valor predeterminado de False.
Cambie el valor de esa propiedad en True.
Se agrega una carpeta de recurso Images al proyecto SharePoint.
Cambie el valor de esa propiedad de nuevo a False.
Si elige el botón Sí en el cuadro de diálogo ¿Elimine la carpeta Images? , la carpeta de recurso Images se elimina del proyecto de SharePoint.
Cierre la instancia experimental de Visual Studio.
Vea también
Conceptos
Extender los proyectos de SharePoint
Cómo: Agregar una propiedad a proyectos de SharePoint
Guardar datos asociados en extensiones del sistema de proyectos de SharePoint
Asociar datos personalizados con extensiones de herramientas de SharePoint