演练:扩展服务器资源管理器以显示 Web 部件

在 Visual Studio 2010 中,您可以使用**“服务器资源管理器”“SharePoint 连接”节点来查看 SharePoint 网站上的组件。 但在默认情况下,“服务器资源管理器”不会显示某些组件。 在本演练中,将扩展“服务器资源管理器”**,以使其显示每个连接的 SharePoint 网站上的 Web 部件库。

本演练将演示以下任务:

  • 创建一个 Visual Studio 扩展,此扩展可通过下列方式扩展**“服务器资源管理器”**:

    • 此扩展会在**“服务器资源管理器”中的每个 SharePoint 网站节点下添加一个新的“Web 部件库”**节点。 该新节点包含的每个子节点均表示网站上的 Web 部件库中的一个 Web 部件。

    • 此扩展会定义一个表示 Web 部件实例的新节点类型。 该新节点类型是新**“Web 部件库”节点下的子节点的基础。 该新 Web 部件节点类型会在“属性”**窗口中显示有关其表示的 Web 部件的信息。 该节点类型还包含一个自定义快捷菜单项,您可以从此菜单项开始执行与 Web 部件相关的其他任务。

  • 创建由扩展程序集调用的两个自定义 SharePoint 命令。 SharePoint 命令是一些方法,扩展程序集可调用这些方法以使用 SharePoint 服务器对象模型中的 API。 在本演练中,您可以创建一些命令,这些命令会从开发计算机上的本地 SharePoint 网站中检索 Web 部件信息。 有关更多信息,请参见调入 SharePoint 对象模型

  • 生成 Visual Studio 扩展 (VSIX) 包以部署扩展。

  • 调试并测试扩展。

提示

有关本演练的替代版本(该版本使用的是 SharePoint 客户端对象模型,而不是服务器对象模型),请参见演练:在服务器资源管理器扩展中调入 SharePoint 客户端对象模型

系统必备

您需要在开发计算机上安装以下组件才能完成本演练:

了解以下概念很有用,但对于完成本演练并不是必需的:

创建项目

若要完成本演练,您需要创建以下三个项目:

  • 一个用于创建 VSIX 包以部署扩展的 VSIX 项目。

  • 一个用于实现扩展的类库项目。 此项目必须面向 .NET Framework 4。

  • 一个用于定义自定义 SharePoint 命令的类库项目。 此项目必须面向 .NET Framework 3.5。

从创建项目开始本演练。

创建 VSIX 项目

  1. 启动 Visual Studio。

  2. 在**“文件”菜单上指向“新建”,再单击“项目”**。

  3. 在**“新建项目”对话框中,展开“Visual C#”“Visual Basic”节点,然后选择“扩展性”**节点。

    提示

    只有在安装 Visual Studio 2010 SDK 之后,“扩展性”节点才可用。 有关更多信息,请参见前面的系统必备部分。

  4. 在对话框顶部的组合框中,选择**“.NET Framework 4”**。

  5. 选择**“VSIX 项目”**模板。

  6. 在**“名称”**框中键入 WebPartNode。

  7. 单击**“确定”**。

    Visual Studio 将**“WebPartNode”项目添加到“解决方案资源管理器”**中。

创建扩展项目

  1. 在**“解决方案资源管理器”中,右击解决方案节点,单击“添加”,再单击“新建项目”**。

    提示

    在 Visual Basic 项目中,仅当在“选项”对话框 ->“项目和解决方案”->“常规”中选中“总是显示解决方案”复选框时,解决方案节点才会出现在“解决方案资源管理器”中。

  2. 在**“新建项目”对话框中,展开“Visual C#”“Visual Basic”节点,然后单击“Windows”**。

  3. 在对话框顶部的组合框中,选择**“.NET Framework 4”**。

  4. 选择**“类库”**项目模板。

  5. 在**“名称”**框中键入 WebPartNodeExtension。

  6. 单击**“确定”**。

    Visual Studio 将**“WebPartNodeExtension”**项目添加到解决方案中,并打开默认的 Class1 代码文件。

  7. 从项目中删除 Class1 代码文件。

创建 SharePoint 命令项目

  1. 在**“解决方案资源管理器”中,右击解决方案节点,单击“添加”,再单击“新建项目”**。

    提示

    在 Visual Basic 项目中,仅当在“选项”对话框 ->“项目和解决方案”->“常规”中选中“总是显示解决方案”复选框时,解决方案节点才会出现在“解决方案资源管理器”中。

  2. 在**“新建项目”对话框中,展开“Visual C#”“Visual Basic”节点,然后单击“Windows”**。

  3. 在对话框顶部的组合框中,选择**“.NET Framework 3.5”**。

  4. 选择**“类库”**项目模板。

  5. 在**“名称”**框中键入 WebPartCommands。

  6. 单击**“确定”**。

    Visual Studio 将**“WebPartCommands”**项目添加到解决方案中,并打开默认的 Class1 代码文件。

  7. 从项目中删除 Class1 代码文件。

配置项目

在编写代码以创建扩展之前,您必须先添加代码文件和程序集引用并配置项目设置。

配置 WebPartNodeExtension 项目

  1. 在 WebPartNodeExtension 项目中添加四个具有下列名称的代码文件:

    • SiteNodeExtension

    • WebPartNodeTypeProvider

    • WebPartNodeInfo

    • WebPartCommandIds

  2. 在**“项目”菜单上,单击“添加引用”**。

  3. 在**“.NET”选项卡上,按住 Ctrl 的同时选择下列程序集,然后单击“确定”**:

    • Microsoft.VisualStudio.SharePoint

    • System.ComponentModel.Composition

    • System.Windows.Forms

  4. 在**“解决方案资源管理器”中,右击“WebPartNodeExtension”项目节点,然后选择“属性”**。

    随即打开**“项目设计器”**。

  5. 单击**“应用程序”**选项卡。

  6. 在**“默认命名空间”框 (C#) 或“根命名空间”**框 (Visual Basic) 中,键入 ServerExplorer.SharePointConnections.WebPartNode。

配置 WebPartCommands 项目

  1. 在 WebPartCommands 项目中添加一个名为 WebPartCommands 的代码文件。

  2. 在**“解决方案资源管理器”中,选择“WebPartCommands”**项目节点。

  3. 在**“项目”菜单上选择“添加现有项”**。

  4. 在**“添加现有项”**对话框中,浏览到包含 WebPartNodeExtension 项目的代码文件的文件夹。

  5. 选择 WebPartNodeInfo 和 WebPartCommandIds 代码文件。

  6. 单击**“添加”按钮的下列菜单并选择“添加为链接”**。

    Visual Studio 将代码文件作为链接添加到 WebPartCommands 项目中。 这意味着代码文件位于 WebPartNodeExtension 项目中,但文件中的代码还是在 WebPartCommands 项目中进行编译。

  7. 在**“项目”菜单上,单击“添加引用”**。

  8. 在**“.NET”选项卡上,按住 Ctrl 的同时选择下列程序集,然后单击“确定”**:

    • Microsoft.SharePoint

    • Microsoft.VisualStudio.SharePoint.Commands

  9. 在**“解决方案资源管理器”中,右击“WebPartCommands”项目节点,然后选择“属性”**。

    随即打开**“项目设计器”**。

  10. 单击**“应用程序”**选项卡。

  11. 在**“默认命名空间”框 (C#) 或“根命名空间”**框 (Visual Basic) 中,键入 ServerExplorer.SharePointConnections.WebPartNode。

为新节点创建图标

为**“服务器资源管理器”扩展创建两个图标:一个图标用于新的“Web 部件库”节点,另一个图标用于“Web 部件库”**节点下的每个子 Web 部件节点。 在本演练后面的部分中,您将编写代码以将这些图标与节点相关联。

为节点创建图标

  1. 在**“解决方案资源管理器”中,右击“WebPartNodeExtension”项目节点,然后选择“属性”**。

  2. 在**“项目”菜单上选择“WebPartNodeExtension 属性”**。

    随即打开**“项目设计器”**。

  3. 单击**“资源”**选项卡。

  4. 单击**“此项目不包含默认资源文件,单击此处创建一个资源文件。”**。

    Visual Studio 将创建一个资源文件并在设计器中打开该文件。

  5. 在设计器的顶部,单击**“添加”按钮上的下拉箭头,再单击“添加新图标”**。

  6. 为新图标名称键入 WebPartsNode,然后单击**“添加”**。

    新图标将在**“图像编辑器”**中打开。

  7. 编辑 16x16 版本的图标,使得设计出的图标可以让您轻松地识别。

  8. 选择 32x32 版的图标。

  9. 在**“图像”菜单上选择“删除图像类型”**。

  10. 重复步骤 5 到步骤 9,将第二个图标添加到项目资源中。 将此图标命名为 WebPart。

  11. 在**“解决方案资源管理器”中的“WebPartNodeExtension”项目的“Resources”文件夹下,选择“WebPartsNode.ico”**。

  12. 在**“属性”窗口中,单击“生成操作”旁边的下拉箭头,然后选择“嵌入的资源”**。

  13. 对于**“WebPart.ico”**,重复最后两个步骤。

向服务器资源管理器中添加 Web 部件库节点

创建一个类,此类可将新的**“Web 部件库”节点添加到每个 SharePoint 网站节点中。 若要添加新节点,此类应实现 IExplorerNodeTypeExtension 接口。 每当需要扩展“服务器资源管理器”**中的现有节点的行为(例如向某个节点添加新的子节点)时,就要实现此接口。

向服务器资源管理器中添加 Web 部件库节点

  1. 在 WebPartNodeExtension 项目中,双击 SiteNodeExtension 代码文件。

  2. 将下面的代码粘贴到此文件中。

    提示

    添加此代码后,项目将会出现一些编译错误。 在添加后面的步骤中的代码之后,这些错误将消失。

    Imports System.Collections.Generic
    Imports System.ComponentModel.Composition
    Imports Microsoft.VisualStudio.SharePoint.Explorer
    
    Namespace ServerExplorer.SharePointConnections.WebPartNode
    
        ' Export attribute: Enables Visual Studio to discover and load this extension.
        ' ExplorerNodeType attribute:  Indicates that this class extends SharePoint site nodes in Server Explorer.
        ' WebPartNodeTypeProvider class: Represents an extension of SharePoint site nodes in Server Explorer.
        <Export(GetType(IExplorerNodeTypeExtension))> _
        <ExplorerNodeType(ExplorerNodeTypes.SiteNode)> _
        Friend Class SiteNodeExtension
            Implements IExplorerNodeTypeExtension
    
            Private Sub Initialize(ByVal nodeType As IExplorerNodeType) _
                Implements IExplorerNodeTypeExtension.Initialize
    
                ' The NodeChildrenRequested event is raised when the user expands the
                ' SharePoint site node in Server Explorer.
                AddHandler nodeType.NodeChildrenRequested, AddressOf NodeChildrenRequested
            End Sub
    
            ' Creates the new Web Part Gallery node with the specified icon.
            Private Sub NodeChildrenRequested(ByVal Sender As Object, ByVal e As ExplorerNodeEventArgs)
    
                ' The CreateWebPartNodes argument is a delegate that Visual Studio calls 
                ' to create the child nodes under the Web Part Gallery node.
                e.Node.ChildNodes.AddFolder("Web Part Gallery", My.Resources.WebPartsNode.ToBitmap(), _
                    AddressOf CreateWebPartNodes)
            End Sub
    
            ' Creates all of the individual Web Part nodes under the new Web Part Gallery node.
            Private Sub CreateWebPartNodes(ByVal parentNode As IExplorerNode)
    
                ' Call the custom SharePoint command to get items from the Web Part gallery.
                Dim webParts = parentNode.Context.SharePointConnection.ExecuteCommand(Of WebPartNodeInfo())( _
                    WebPartCommandIds.GetWebParts)
                If webParts IsNot Nothing Then
                    For Each webPart As WebPartNodeInfo In webParts
    
                        ' Create a new annotation object to store the current Web Part item with the new node.
                        Dim annotations = New Dictionary(Of Object, Object)()
                        annotations.Add(GetType(WebPartNodeInfo), webPart)
    
                        ' Create the new node for the current Web Part item.
                        parentNode.ChildNodes.Add(WebPartNodeTypeProvider.WebPartNodeTypeId, _
                            webPart.Name, annotations)
                    Next
                End If
            End Sub
    
        End Class
    End Namespace
    
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.SharePoint.Explorer;
    
    namespace ServerExplorer.SharePointConnections.WebPartNode
    {
        // Enables Visual Studio to discover and load this extension.
        [Export(typeof(IExplorerNodeTypeExtension))]        
    
        // Indicates that this class extends SharePoint site nodes in Server Explorer.
        [ExplorerNodeType(ExplorerNodeTypes.SiteNode)]
    
        // Represents an extension of SharePoint site nodes in Server Explorer.
        internal class SiteNodeExtension : IExplorerNodeTypeExtension
        {
            public void Initialize(IExplorerNodeType nodeType)
            {
                // The NodeChildrenRequested event is raised when the user expands the
                // SharePoint site node in Server Explorer.
                nodeType.NodeChildrenRequested += NodeChildrenRequested;
            }
    
            // Creates the new Web Part Gallery node with the specified icon.
            private void NodeChildrenRequested(object sender, ExplorerNodeEventArgs e)
            {
                // The CreateWebPartNodes argument is a delegate that Visual Studio calls 
                // to create the child nodes under the Web Part Gallery node.
                e.Node.ChildNodes.AddFolder("Web Part Gallery",
                    Properties.Resources.WebPartsNode.ToBitmap(), CreateWebPartNodes);
            }
    
            // Creates all of the individual Web Part nodes under the new Web Part Gallery node.
            private void CreateWebPartNodes(IExplorerNode parentNode)
            {
                // Call the custom SharePoint command to get items from the Web Part gallery.
                var webParts = parentNode.Context.SharePointConnection.ExecuteCommand<WebPartNodeInfo[]>(
                    WebPartCommandIds.GetWebParts);
    
                if (webParts != null)
                {
                    foreach (WebPartNodeInfo webPart in webParts)
                    {
                        // Create a new annotation object to store the current Web Part item with the new node.
                        var annotations = new Dictionary<object, object>() 
                        { 
                            { typeof(WebPartNodeInfo), webPart } 
                        };
    
                        // Create the new node for the current Web Part item.
                        parentNode.ChildNodes.Add(WebPartNodeTypeProvider.WebPartNodeTypeId,
                            webPart.Name, annotations);
                    }
                }
            }
        }
    }
    

定义表示 Web 部件的节点类型

创建一个类,此类定义表示 Web 部件的新节点类型。 Visual Studio 使用此新节点类型来显示**“Web 部件库”**节点下的子节点。 其中的每个子节点均表示 SharePoint 网站上的一个 Web 部件。

若要定义新节点类型,此类应实现 IExplorerNodeTypeProvider 接口。 每当需要在**“服务器资源管理器”**中定义新的节点类型时,就要实现此接口。

定义 Web 部件节点类型

  1. 在 WebPartNodeExtension 项目中,双击 WebPartNodeTypeProvder 代码文件。

  2. 将下面的代码粘贴到此文件中。

    Imports System
    Imports System.Collections.Generic
    Imports System.Windows.Forms
    Imports System.ComponentModel.Composition
    Imports Microsoft.VisualStudio.SharePoint
    Imports Microsoft.VisualStudio.SharePoint.Explorer
    
    Namespace ServerExplorer.SharePointConnections.WebPartNode
    
        ' Export attribute: Enables Visual Studio to discover and load this extension.
        ' ExplorerNodeType attribute: Specifies the ID for this new node type.
        ' WebPartNodeTypeProvider class: Defines a new node type that represents a Web Part on a SharePoint site.
        <Export(GetType(IExplorerNodeTypeProvider))> _
        <ExplorerNodeType(WebPartNodeTypeProvider.WebPartNodeTypeId)> _
        Friend Class WebPartNodeTypeProvider
            Implements IExplorerNodeTypeProvider
    
            Friend Const WebPartNodeTypeId As String = "Contoso.WebPart"
    
            Private Sub InitializeType(ByVal typeDefinition As IExplorerNodeTypeDefinition) _
                Implements IExplorerNodeTypeProvider.InitializeType
    
                typeDefinition.DefaultIcon = My.Resources.WebPart.ToBitmap()
                typeDefinition.IsAlwaysLeaf = True
                AddHandler typeDefinition.NodePropertiesRequested, AddressOf NodePropertiesRequested
            End Sub
    
            ' Retrieves properties that are displayed in the Properties window when
            ' a Web Part node is selected.
            Private Sub NodePropertiesRequested(ByVal Sernder As Object, _
                ByVal e As ExplorerNodePropertiesRequestedEventArgs)
    
                Dim nodeInfo = e.Node.Annotations.GetValue(Of WebPartNodeInfo)()
    
                ' Call the custom SharePoint command to get the Web Part properties.
                Dim properties As Dictionary(Of String, String) = _
                    e.Node.Context.SharePointConnection.ExecuteCommand( _
                    Of WebPartNodeInfo, Dictionary(Of String, String))(
                    WebPartCommandIds.GetWebPartProperties, nodeInfo)
                Dim propertySource As Object = e.Node.Context.CreatePropertySourceObject(properties)
                e.PropertySources.Add(propertySource)
            End Sub
    
        End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.SharePoint;
    using Microsoft.VisualStudio.SharePoint.Explorer;
    
    namespace ServerExplorer.SharePointConnections.WebPartNode
    {
        // Enables Visual Studio to discover and load this extension.
        [Export(typeof(IExplorerNodeTypeProvider))]
    
        // Specifies the ID for this new node type.
        [ExplorerNodeType(WebPartNodeTypeProvider.WebPartNodeTypeId)]
    
        // Defines a new node type that represents a Web Part on a SharePoint site.
        internal class WebPartNodeTypeProvider : IExplorerNodeTypeProvider
        {
            internal const string WebPartNodeTypeId = "Contoso.WebPart";
    
            public void InitializeType(IExplorerNodeTypeDefinition typeDefinition)
            {
                typeDefinition.DefaultIcon = Properties.Resources.WebPart.ToBitmap();
                typeDefinition.IsAlwaysLeaf = true;
                typeDefinition.NodePropertiesRequested += NodePropertiesRequested;
            }
    
            // Retrieves properties that are displayed in the Properties window when
            // a Web Part node is selected.
            private void NodePropertiesRequested(object sender,
                ExplorerNodePropertiesRequestedEventArgs e)
            {
                var webPartNodeInfo = e.Node.Annotations.GetValue<WebPartNodeInfo>();
    
                // Call the custom SharePoint command to get the Web Part properties.
                Dictionary<string, string> properties =
                    e.Node.Context.SharePointConnection.ExecuteCommand<
                    WebPartNodeInfo, Dictionary<string, string>>(
                    WebPartCommandIds.GetWebPartProperties, webPartNodeInfo);
    
                object propertySource = e.Node.Context.CreatePropertySourceObject(properties);
                e.PropertySources.Add(propertySource);
            }
        }
    }
    

定义 Web 部件数据类

定义一个类,此类包含有关 SharePoint 网站上的单个 Web 部件的数据。 在本演练后面的部分中,您将创建一条自定义 SharePoint 命令,此命令将检索有关网站上每个 Web 部件的数据,然后将数据分配给此类的实例。

定义 Web 部件数据类

  1. 在 WebPartNodeExtension 项目中,双击 WebPartNodeInfo 代码文件。

  2. 将下面的代码粘贴到此文件中。

    Imports System
    
    Namespace ServerExplorer.SharePointConnections.WebPartNode
    
        ' Contains basic data about a single Web Part on the SharePoint site. This class is 
        ' serializable so that instances of it can be sent between the WebPartNode and 
        ' WebPartCommands assemblies.
        <Serializable()> _
        Public Class WebPartNodeInfo
    
            Private siteIdValue As Guid
            Public Property SiteId As Guid
                Get
                    Return siteIdValue
                End Get
                Set(ByVal value As Guid)
                    siteIdValue = value
                End Set
            End Property
    
            Private idValue As Integer
            Public Property Id As Integer
                Get
                    Return idValue
                End Get
                Set(ByVal value As Integer)
                    idValue = value
                End Set
            End Property
    
            Private uniqueIdValue As Guid
            Public Property UniqueId As Guid
                Get
                    Return uniqueIdValue
                End Get
                Set(ByVal value As Guid)
                    uniqueIdValue = value
                End Set
            End Property
    
            Private nameValue As String
            Public Property Name As String
                Get
                    Return nameValue
                End Get
                Set(ByVal value As String)
                    nameValue = value
                End Set
            End Property
    
            Private imageUrlValue As String
            Public Property ImageUrl As String
                Get
                    Return imageUrlValue
                End Get
                Set(ByVal value As String)
                    imageUrlValue = value
                End Set
            End Property
    
        End Class
    End Namespace
    
    using System;
    
    namespace ServerExplorer.SharePointConnections.WebPartNode
    {
        // Contains basic data about a single Web Part on the SharePoint site. This class is 
        // serializable so that instances of it can be sent between the WebPartNode and 
        // WebPartCommands assemblies.
        [Serializable]
        public class WebPartNodeInfo
        {
            public Guid SiteId { get; set; }
            public int Id { get; set; }
            public Guid UniqueId { get; set; }
            public string Name { get; set; }
            public string ImageUrl { get; set; }
        }
    }
    

定义 SharePoint 命令的 ID

定义若干个标识自定义 SharePoint 命令的字符串。 您将在本演练后面的部分中实现这些命令。

定义命令 ID

  1. 在 WebPartNodeExtension 项目中,双击 WebPartCommandIds 代码文件。

  2. 将下面的代码粘贴到此文件中。

    Namespace ServerExplorer.SharePointConnections.WebPartNode
    
        Public Class WebPartCommandIds
            Public Const GetWebParts As String = "WebPart.GetWebParts"
            Public Const GetWebPartProperties As String = "WebPart.GetProperties"
        End Class
    
    End Namespace
    
    namespace ServerExplorer.SharePointConnections.WebPartNode
    {
        public static class WebPartCommandIds
        {
            public const string GetWebParts = "WebPart.GetWebParts";
            public const string GetWebPartProperties = "WebPart.GetProperties";
        }
    }
    

创建自定义 SharePoint 命令

创建自定义命令,这些命令将调入 SharePoint 服务器对象模型,以检索有关 SharePoint 网站上的 Web 部件的数据。 每条命令均是应用了 SharePointCommandAttribute 的方法。

定义 SharePoint 命令

  1. 在“WebPartCommands”项目中,双击 WebPartCommands 代码文件。

  2. 将下面的代码粘贴到此文件中。

    Imports System.Collections.Generic
    Imports Microsoft.SharePoint
    Imports Microsoft.VisualStudio.SharePoint.Commands
    
    Namespace ServerExplorer.SharePointConnections.WebPartNode
    
        Friend Class WebPartsCommands
    
            ' Gets data for each Web Part on the SharePoint site, and returns an array of 
            ' serializable objects that contain the data.
            <SharePointCommand(WebPartCommandIds.GetWebParts)> _
            Private Shared Function GetWebParts(ByVal context As ISharePointCommandContext) As WebPartNodeInfo()
    
                Dim nodeInfos = New List(Of WebPartNodeInfo)()
                Dim webParts As SPListItemCollection = context.Site.GetCatalog( _
                    SPListTemplateType.WebPartCatalog).Items
    
                For Each webPart As SPListItem In webParts
                    Dim nodeInfo As WebPartNodeInfo = New WebPartNodeInfo()
                    With nodeInfo
                        .Id = webPart.ID
                        .SiteId = webPart.ParentList.ParentWeb.ID
                        .Name = webPart.Title
                        .UniqueId = webPart.UniqueId
                        .ImageUrl = webPart.ParentList.ImageUrl
                    End With
                    nodeInfos.Add(nodeInfo)
                Next
                Return nodeInfos.ToArray()
            End Function
    
            ' Gets additional property data for a specific Web Part.
            <SharePointCommand(WebPartCommandIds.GetWebPartProperties)> _
            Private Shared Function GetWebPartProperties(ByVal context As ISharePointCommandContext, _
                ByVal webPartNodeInfo As WebPartNodeInfo) As Dictionary(Of String, String)
    
                Dim webParts As SPList = context.Site.GetCatalog(SPListTemplateType.WebPartCatalog)
                Dim webPart As SPListItem = webParts.Items(webPartNodeInfo.UniqueId)
                Return SharePointCommandServices.GetProperties(webPart)
            End Function
        End Class
    End Namespace
    
    using System.Collections.Generic;
    using Microsoft.SharePoint;
    using Microsoft.VisualStudio.SharePoint.Commands;
    
    namespace ServerExplorer.SharePointConnections.WebPartNode
    {
        internal class WebPartsCommands
        {
            // Gets data for each Web Part on the SharePoint site, and returns an array of 
            // serializable objects that contain the data.
            [SharePointCommand(WebPartCommandIds.GetWebParts)]
            private static WebPartNodeInfo[] GetWebParts(ISharePointCommandContext context)
            {
                var nodeInfos = new List<WebPartNodeInfo>();
                SPListItemCollection webParts = context.Site.GetCatalog(
                    SPListTemplateType.WebPartCatalog).Items;
    
                foreach (SPListItem webPart in webParts)
                {
                    WebPartNodeInfo nodeInfo = new WebPartNodeInfo
                    {
                        Id = webPart.ID,
                        SiteId = webPart.ParentList.ParentWeb.ID,
                        Name = webPart.Title,
                        UniqueId = webPart.UniqueId,
                        ImageUrl = webPart.ParentList.ImageUrl
                    };
                    nodeInfos.Add(nodeInfo);
                }
    
                return nodeInfos.ToArray();
            }
    
            // Gets additional property data for a specific Web Part.
            [SharePointCommand(WebPartCommandIds.GetWebPartProperties)]
            private static Dictionary<string, string> GetWebPartProperties(ISharePointCommandContext context, 
                WebPartNodeInfo nodeInfo)
            {
                SPList webParts = context.Site.GetCatalog(SPListTemplateType.WebPartCatalog);
                SPListItem webPart = webParts.Items[nodeInfo.UniqueId];
    
                return SharePointCommandServices.GetProperties(webPart);
            }
        }
    }
    

检查点

演练进行到此时,**“Web 部件库”**节点和 SharePoint 命令的所有代码现在都位于项目中。 生成解决方案以确保项目在编译时不会出错。

生成解决方案

  • 在**“生成”菜单上,选择“生成解决方案”**。

创建 VSIX 包以部署扩展

若要部署扩展,请使用解决方案中的 VSIX 项目来创建 VSIX 包。 首先,通过修改 VSIX 项目中包含的 source.extension.vsixmanifest 文件来配置 VSIX 包。 然后,通过生成解决方案来创建 VSIX 包。

配置 VSIX 包

  1. 在**“解决方案资源管理器”中,双击 WebPartNode 项目下的“source.extension.vsixmanifest”**文件。

    Visual Studio 将在清单编辑器中打开该文件。 source.extension.vsixmanifest 文件是所有 VSIX 包必需的 extension.vsixmanifest 文件的基础。 有关此文件的更多信息,请参见VSIX Extension Schema Reference

  2. 在**“产品名称”**框中,键入“服务器资源管理器的 Web 部件库节点”。

  3. 在**“作者”**框中键入 Contoso。

  4. 在**“说明”**框中,键入“向服务器资源管理器中的 SharePoint 连接节点添加自定义 Web 部件库节点。此扩展使用自定义 SharePoint 命令调入服务器对象模型。”。

  5. 在编辑器的**“内容”部分中,单击“添加内容”**按钮。

  6. 在**“添加内容”对话框的“选择内容类型”列表框中,选择“MEF 组件”**。

    提示

    此值对应于 extension.vsixmanifest 文件中的 MefComponent 元素。 此元素指定 VSIX 包中的扩展程序集的名称。 有关更多信息,请参见 MEFComponent Element (VSX Schema)

  7. 在**“选择源”下,单击“项目”单选按钮,并在其旁边的列表框中选择“WebPartNodeExtension”**。

  8. 单击**“确定”**。

  9. 在清单编辑器中,再次单击**“添加内容”**按钮。

  10. 在**“添加内容”对话框的“选择内容类型”列表框中,选择“自定义扩展类型”**。

    提示

    此值对应于 extension.vsixmanifest 文件中的 CustomExtension 元素。 此元素指定要包括在 Visual Studio 扩展中的自定义扩展。 有关更多信息,请参见 CustomExtension Element (VSX Schema)

  11. 在**“类型”**文本框中,键入 SharePoint.Commands.v4。

    提示

    此值对应于 extension.vsixmanifest 文件中的 CustomExtension 元素的 Type 特性。 值 Sharepoint.Commands.v4 是包含自定义 SharePoint 命令的所有自定义扩展程序集所必需的。

  12. 在**“选择源”下,单击“项目”单选按钮,并在其旁边的列表框中选择“WebPartCommands”**。

  13. 单击**“确定”**。

  14. 在**“生成”菜单上,单击“生成解决方案”**。 确保编译解决方案时不会出错。

  15. 打开 WebPartNode 项目的生成输出文件夹。 确保此文件夹此时包含 WebPartNode.vsix 文件。

    默认情况下,生成输出文件夹为 包含项目文件的文件夹下的 ..\bin\Debug 文件夹。

测试扩展

此时,您可以对**“服务器资源管理器”中的新“Web 部件库”节点进行测试。 首先,在 Visual Studio 的实验实例中开始调试扩展。 然后,在 Visual Studio 的实验实例中使用新的“Web 部件”**节点。

开始调试扩展

  1. 利用管理员特权重新启动 Visual Studio 并打开 WebPartNode 解决方案。

  2. 在 WebPartNodeExtension 项目中,打开 SiteNodeExtension 代码文件,并向 NodeChildrenRequested 和 CreateWebPartNodes 方法的第一个代码行中添加一个断点。

  3. F5 开始调试。

    Visual Studio 将扩展安装到 %UserProfile%\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions\Contoso\Web Part Gallery Node Extension for Server Explorer\1.0 中,并启动 Visual Studio 的实验实例。 您将在此 Visual Studio 实例中测试项目项。

测试扩展

  1. 在 Visual Studio 的实验实例中,在**“视图”菜单上单击“服务器资源管理器”**。

  2. 验证要用于测试的 SharePoint 网站是否显示在**“服务器资源管理器”中的“SharePoint 连接”**节点下。 如果未列出此网站,请执行下列步骤:

    1. 右击**“SharePoint 连接”,然后单击“添加连接”**。

    2. 在**“添加 SharePoint 连接”**对话框中,输入要连接到的 SharePoint 网站的 URL。 若要指定开发计算机上的 SharePoint 网站,请键入 https://localhost。

    3. 单击**“确定”**。

  3. 展开网站集节点(即显示网站的 URL 的节点),再展开子网站节点(例如**“团队网站”**)。

  4. 验证另一个 Visual Studio 实例中的代码是否会在您之前在 NodeChildrenRequested 方法中设置的断点处停止。 按 F5 以继续调试项目。

  5. 在 Visual Studio 的实验实例中,验证名为**“Web 部件库”的新节点是否显示在首要网站节点下。 展开“Web 部件库”**节点。

  6. 验证另一个 Visual Studio 实例中的代码是否会在您之前在 CreateWebPartNodes 方法中设置的断点处停止。 按 F5 以继续调试项目。

  7. 在 Visual Studio 的实验实例中,验证已连接网站上的所有 Web 部件是否都显示在**“服务器资源管理器”中的“Web 部件库”**节点下。

  8. 右击其中的某个 Web 部件,然后单击**“属性”**。

  9. 在所调试的 Visual Studio 实例中,验证有关 Web 部件的详细信息是否显示在**“属性”**窗口中。

从 Visual Studio 中卸载扩展

测试完扩展后,请从 Visual Studio 卸载扩展。

卸载扩展

  1. 在 Visual Studio 的实验实例中,在**“工具”菜单上单击“扩展管理器”**。

    这将打开**“扩展管理器”**对话框。

  2. 在扩展列表中,选择**“服务器资源管理器的 Web 部件库节点扩展”,然后单击“卸载”**。

  3. 在出现的对话框中,单击**“是”**以确认您要卸载该扩展。

  4. 单击**“立即重新启动”**以完成卸载。

  5. 关闭 Visual Studio 的两个实例(Visual Studio 的实验实例和 Visual Studio 的已打开 WebPartNode 解决方案的实例)。

请参见

任务

演练:在服务器资源管理器扩展中调入 SharePoint 客户端对象模型

创建新位图或其他图像

参考

图像编辑器

其他资源

扩展服务器资源管理器中的“SharePoint 连接”节点