How to: Add a Property to SharePoint Projects

You can use a project extension to add a property to any SharePoint project. The property appears in the Properties window when the project is selected in Solution Explorer.

The following steps assume that you have already created a project extension. For more information, see How to: Create a SharePoint Project Extension.

To add a property to a SharePoint project

  1. Define a class with a public property that represents the property you are adding to SharePoint projects. If you want to add multiple properties, you can define all the properties in the same class or in different classes.

  2. In the Initialize method of your ISharePointProjectExtension implementation, handle the ProjectPropertiesRequested event of the projectService parameter.

  3. In the event handler for the ProjectPropertiesRequested event, add an instance of your properties class to the PropertySources collection of the event arguments parameter.

Example

The following code example demonstrates how to add two properties to SharePoint projects. One property persists its data in the project user option file (the .csproj.user file or .vbproj.user file). The other property persists its data in the project file (.csproj file or .vbproj file).

Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Composition
Imports Microsoft.VisualStudio
Imports Microsoft.VisualStudio.SharePoint
Imports Microsoft.VisualStudio.Shell.Interop

Namespace CustomSharePointProperty

    <Export(GetType(ISharePointProjectExtension))> _
    Partial Friend Class ProjectExtensionWithProperty
        Implements ISharePointProjectExtension

        Public Sub Initialize(ByVal projectService As ISharePointProjectService) _
            Implements ISharePointProjectExtension.Initialize
            AddHandler projectService.ProjectPropertiesRequested, _
                AddressOf ProjectPropertiesRequested
        End Sub 

        Private Sub 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
        Private projectStorage As IVsBuildPropertyStorage
        Private Const ProjectFilePropertyId As String = "ContosoCustomProjectFileProperty" 
        Private Const ProjectFilePropertyDefaultValue As String = "Default" 

        Public Sub New(ByVal myProject As ISharePointProject)
            sharePointProject = myProject
            projectStorage = sharePointProject.ProjectService.Convert(Of ISharePointProject, IVsBuildPropertyStorage)(sharePointProject)
        End Sub

        <DisplayName("Custom Project File Property")> _
        <DescriptionAttribute("This property is saved to the .csproj/.vbproj file.")> _
        <DefaultValue(ProjectFilePropertyDefaultValue)> _
        Public Property CustomProjectFileProperty As String 
            Get 
                Dim propertyValue As String = String.Empty
                Dim hr As Integer = projectStorage.GetPropertyValue(ProjectFilePropertyId, String.Empty, _
                    CUInt(_PersistStorageType.PST_PROJECT_FILE), propertyValue)

                ' Try to get the current value from the project file; if it does not yet exist, return a default value. 
                If Not ErrorHandler.Succeeded(hr) Or String.IsNullOrEmpty(propertyValue) Then
                    propertyValue = ProjectFilePropertyDefaultValue
                End If 
                Return propertyValue
            End Get 
            Set(ByVal value As String)
                ' Do not save the default value. 
                If value <> ProjectFilePropertyDefaultValue Then
                    projectStorage.SetPropertyValue(ProjectFilePropertyId, String.Empty, _
                        CUInt(_PersistStorageType.PST_PROJECT_FILE), value)
                End If 
            End Set 
        End Property 

        Private Const UserFilePropertyId As String = "ContosoCustomUserFileProperty" 
        Private Const UserFilePropertyDefaultValue As String = "Default"

        <DisplayName("Custom Project User File Property")> _
        <DescriptionAttribute("This property is saved to the .user file.")> _
        <DefaultValue(UserFilePropertyDefaultValue)> _
        Public Property CustomUserFileProperty As String 
            Get 
                Dim propertyValue 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(UserFilePropertyId, propertyValue) Then
                    propertyValue = UserFilePropertyDefaultValue
                End If 
                Return propertyValue
            End Get 
            Set(ByVal value As String)
                ' Do not save the default value. 
                If value <> UserFilePropertyDefaultValue Then
                    sharePointProject.ProjectUserFileData(UserFilePropertyId) = value
                End If 
            End Set 
        End Property 
    End Class 
End Namespace
using System;
using System.ComponentModel;
using System.ComponentModel.Composition;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.SharePoint;
using Microsoft.VisualStudio.Shell.Interop;

namespace CustomSharePointProperty
{
    [Export(typeof(ISharePointProjectExtension))]
    public class ProjectExtensionWithProperty : ISharePointProjectExtension
    {
        public void Initialize(ISharePointProjectService projectService)
        {
            projectService.ProjectPropertiesRequested += projectService_ProjectPropertiesRequested;           
        }

        void projectService_ProjectPropertiesRequested(object sender, SharePointProjectPropertiesRequestedEventArgs e)
        {
            CustomProjectProperties propertiesObject;

            // If the properties object already exists, get it from the project's annotations. 
            if (!e.Project.Annotations.TryGetValue(out propertiesObject))
            {
                // Otherwise, create a new properties object and add it to the annotations.
                propertiesObject = new CustomProjectProperties(e.Project);
                e.Project.Annotations.Add(propertiesObject);
            }

            e.PropertySources.Add(propertiesObject);
        }
    }

    public class CustomProjectProperties
    {
        private ISharePointProject sharePointProject;
        private IVsBuildPropertyStorage projectStorage;
        private const string ProjectFilePropertyId = "ContosoCustomProjectFileProperty";
        private const string ProjectFilePropertyDefaultValue = "Default";

        public CustomProjectProperties(ISharePointProject myProject)
        {
            sharePointProject = myProject;
            projectStorage = sharePointProject.ProjectService.Convert<ISharePointProject, IVsBuildPropertyStorage>(sharePointProject);
        }

        [DisplayName("Custom Project File Property")]
        [DescriptionAttribute("This property is saved to the .csproj/.vbproj file.")]
        [DefaultValue(ProjectFilePropertyDefaultValue)]
        public string CustomProjectFileProperty
        {
            get
            {
                string propertyValue;
                int hr = projectStorage.GetPropertyValue(ProjectFilePropertyId, string.Empty, 
                    (uint)_PersistStorageType.PST_PROJECT_FILE, out propertyValue);

                // Try to get the current value from the project file; if it does not yet exist, return a default value. 
                if (!ErrorHandler.Succeeded(hr) || String.IsNullOrEmpty(propertyValue))
                {
                    propertyValue = ProjectFilePropertyDefaultValue;
                }

                return propertyValue;
            }

            set
            {
                // Do not save the default value. 
                if (value != ProjectFilePropertyDefaultValue)
                {
                    projectStorage.SetPropertyValue(ProjectFilePropertyId, string.Empty, 
                        (uint)_PersistStorageType.PST_PROJECT_FILE, value);
                }
            }
        }

        private const string UserFilePropertyId = "ContosoCustomUserFileProperty";
        private const string UserFilePropertyDefaultValue = "Default";

        [DisplayName("Custom Project User File Property")]
        [DescriptionAttribute("This property is saved to the .user file.")]
        [DefaultValue(UserFilePropertyDefaultValue)]
        public string CustomUserFileProperty
        {
            get
            {
                string propertyValue = string.Empty;

                // Try to get the current value from the .user file; if it does not yet exist, return a default value. 
                if (!sharePointProject.ProjectUserFileData.TryGetValue(UserFilePropertyId, out propertyValue))
                {
                    propertyValue = UserFilePropertyDefaultValue; 
                }

                return propertyValue; 
            }

            set
            {
                // Do not save the default value. 
                if (value != UserFilePropertyDefaultValue)
                {
                    sharePointProject.ProjectUserFileData[UserFilePropertyId] = value;
                }
            }
        }                
    }
}

Understanding the Code

To ensure that the same instance of the CustomProjectProperties class is used each time the ProjectPropertiesRequested event occurs, the code example adds the properties object to the Annotations property of the project the first time this event occurs. The code retrieves this object whenever this event occurs again. For more information about using the Annotations property to associate data with projects, see Associating Custom Data with SharePoint Tools Extensions.

To persist changes to the property values, the set accessors for the properties use the following APIs:

For more information about persisting data in these files, see Saving Data in Extensions of the SharePoint Project System.

Specifying the Behavior of Custom Properties

You can define how a custom property appears and behaves in the Properties window by applying attributes from the System.ComponentModel namespace to the property definition. The following attributes are useful in many scenarios:

  • DisplayNameAttribute: Specifies the name of the property that appears in the Properties window.

  • DescriptionAttribute: Specifies the description string that appears in the bottom of the Properties window when the property is selected.

  • DefaultValueAttribute: Specifies the default value of the property.

  • TypeConverterAttribute: Specifies a custom conversion between the string that is displayed in the Properties window and a non-string property value.

  • EditorAttribute: Specifies a custom editor to use to modify the property.

Compiling the Code

This example requires references to the following assemblies:

  • Microsoft.VisualStudio.SharePoint

  • Microsoft.VisualStudio.Shell

  • Microsoft.VisualStudio.Shell.Interop

  • Microsoft.VisualStudio.Shell.Interop.8.0

  • System.ComponentModel.Composition

Deploying the Extension

To deploy the extension, create a Visual Studio extension (VSIX) package for the assembly and any other files that you want to distribute with the extension. For more information, see Deploying Extensions for the SharePoint Tools in Visual Studio.

See Also

Concepts

Extending SharePoint Projects

How to: Create a SharePoint Project Extension

How to: Add a Shortcut Menu Item to SharePoint Projects

Extending the SharePoint Project System