This topic has not yet been rated - Rate this topic

Walkthrough: Creating a SharePoint Project Extension

This walkthrough illustrates how to create an extension for SharePoint projects. You can use a project extension to respond to project-level events such as a when a project is added, deleted, or its name changed. You can also add custom properties or respond when a property value changes. Unlike project item extensions, project extensions cannot be associated with a particular SharePoint project type. When you create a project extension, the extension loads when any kind of SharePoint project is opened in Visual Studio.

In this walkthrough, you will create a custom Boolean property that is added to any SharePoint project created in Visual Studio. When set to True, the new property adds, or maps, an Images resource folder to your project. When set to False, the Images folder is removed, if it exists. For more information, see How to: Add and Remove Mapped Folders.

This walkthrough demonstrates the following tasks:

  • Creating a Visual Studio extension for SharePoint projects that does the following:

    • Adds a custom project property to the Properties window. The property applies to any SharePoint project.

    • Uses the SharePoint project object model to add a mapped folder to a project.

    • Uses the Visual Studio automation object model (DTE) to delete a mapped folder from the project.

  • Building a Visual Studio Extension (VSIX) package to deploy the project property's extension assembly.

  • Debugging and testing the project property.

You need the following components on the development computer to complete this walkthrough:

To complete this walkthrough, you must create two projects:

  • A VSIX project to create the VSIX package to deploy the project extension.

  • A class library project that implements the project extension.

Start the walkthrough by creating the projects.

To create the VSIX project

  1. Start Visual Studio.

  2. On the File menu, point to New, and then click Project.

  3. In the New Project dialog box, expand the Visual C# or Visual Basic nodes, and then click the Extensibility node.

    NoteNote

    The Extensibility node is available only if you install the Visual Studio 2010 SDK. For more information, see the prerequisites section earlier in this topic will.

  4. In the combo box at the top of the dialog box, select .NET Framework 4. SharePoint tools extensions require features in this version of the .NET Framework.

  5. Click the VSIX Project template.

  6. In the Name box, type ProjectExtensionPackage.

  7. Click OK.

    Visual Studio adds the ProjectExtensionPackage project to Solution Explorer.

To create the extension project

  1. In Solution Explorer, right-click the solution node, click Add, and then click New Project.

    NoteNote

    In Visual Basic projects, the solution node appears in Solution Explorer only when the Always show solution check box is selected in the General, Projects and Solutions, Options Dialog Box.

  2. In the New Project dialog box, expand the Visual C# or Visual Basic nodes, and then click Windows.

  3. In the combo box at the top of the dialog box, select .NET Framework 4.

  4. Select the Class Library project template.

  5. In the Name box, type ProjectExtension.

  6. Click OK.

    Visual Studio adds the ProjectExtension project to the solution and opens the default Class1 code file.

  7. Delete the Class1 code file from the project.

Before you write code to create the project extension, add code files and assembly references to the extension project.

To configure the project

  1. Add a new code file named CustomProperty to the ProjectExtension project.

  2. On the Project menu, click Add Reference.

  3. On the .NET tab, press CTRL and then click the following assemblies, and then click OK:

    • Microsoft.VisualStudio.SharePoint

    • System.ComponentModel.Composition

    • System.Windows.Forms

    • EnvDTE

  4. In Solution Explorer, under the References folder for the ProjectExtension project, click EnvDTE.

  5. In the Properties window, change the Embed Interop Types property to False.

Create a class that defines the project extension and the behavior of the new project property. To define the new project extension, the class implements the ISharePointProjectExtension interface. Implement this interface whenever you want to define an extension for a SharePoint project. Also, add the ExportAttribute to the class. This attribute enables Visual Studio to discover and load your ISharePointProjectExtension implementation. Pass the ISharePointProjectExtension type to the attribute's constructor.

To define the new SharePoint project property

  1. Double-click the CustomProperty code file to edit it, if it is not already open.

  2. Paste the following code into the file.

    
    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;
    
            }
        }
    }
    
    
    

Next, build the solution to make sure that it compiles without errors.

To build the solution

  • On the Build menu, click Build Solution.

To deploy the project extension, use the VSIX project in your solution to create a VSIX package. First, configure the VSIX package by modifying the source.extension.vsixmanifest file that is included in the VSIX project. Then, create the VSIX package by building the solution.

To configure and create the VSIX package

  1. In Solution Explorer, double-click the source.extension.vsixmanifest file.

    Visual Studio opens the file in the manifest editor. This editor provides a UI you can use to edit the XML in the manifest. This information displays later in the Extension Manager. The extension.vsixmanifest file is required by all VSIX packages. For more information about this file, see VSIX Extension Schema Reference.

  2. In the Product Name box, type Custom Project Property.

  3. In the Author box, type Contoso.

  4. In the Description box, type A custom SharePoint project property that toggles the mapping of the Images resource folder to the project.

  5. In the Content section of the editor, click the Add Content button.

  6. Select MEF Component in the Select a content type drop-down box.

    NoteNote

    This value corresponds to the MEFComponent element in the extension.vsixmanifest file. This element specifies the name of an extension assembly in the VSIX package. For more information, see MEFComponent Element (VSX Schema).

  7. In the Select a source section, click the Project option, then select ProjextExtension in the drop-down box.

    This value identifies the name of the assembly that you are building in the project.

  8. When you are finished, click OK to close the Add Content dialog box.

  9. When you are finished, click Save All on the File menu and then close the manifest designer.

  10. On the Build menu, click Build Solution. Make sure that the project compiles without errors.

  11. Click the ProjectExtensionPackage project in Solution Explorer, click the Show All Files button, and then open the build output folder for the ProjectExtensionPackage project. This folder should now contain a file that is named ProjectExtensionPackage.vsix.

    By default, the build output folder is the ..\bin\Debug folder under the folder that contains your project file.

You are now ready to test the custom project property. It is easiest to debug and test the new project property extension in an experimental instance of Visual Studio. This is the instance of Visual Studio that is created when you run a VSIX or other extensibility project. After the project is debugged, you can install the extension on your system, and then continue to debug and test it in a regular instance of Visual Studio.

To debug and test the extension in an experimental instance of Visual Studio

  1. Restart Visual Studio with administrative credentials and open the ProjectExtensionPackage solution.

  2. Press F5 to start a debug build of your project.

    Visual Studio installs the extension to %UserProfile%\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions\Contoso\Custom Project Property\1.0 and starts an experimental instance of Visual Studio.

  3. In the experimental instance of Visual Studio, create a new farm solution SharePoint project, such as a Module. Use the default values for the other values in the wizard.

  4. Click the project node in Solution Explorer.

    A new custom property Map Images Folder appears in the Properties window with a default value of False.

  5. Change Map Images Folder to True.

    An Images resource folder is added to the SharePoint project.

  6. Change Map Images Folder to False.

    The Images resource folder is deleted from the SharePoint project.

  7. Close the experimental instance of Visual Studio.

Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

ADD
Show:
© 2014 Microsoft. All rights reserved.