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

本演练演示如何从**“服务器资源管理器”中的“SharePoint 连接”**节点扩展调用 SharePoint 客户端对象模型。有关如何使用 SharePoint 客户端对象模型的更多信息,请参见 调入 SharePoint 对象模型

本演练将演示以下任务:

  • 创建一个 Visual Studio 扩展,此扩展通过以下方式扩展**“服务器资源管理器”“SharePoint 连接”**节点:

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

    • 扩展定义表示 Web 部件实例新的节点。该新节点类型是新**“Web 部件库”**节点下的子节点的基础。该新 Web 部件节点类型显示在 属性 窗口中有关该节点表示的 Web 部件。

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

  • 调试并测试扩展。

说明说明

在本演练中创建的扩展类似于您在 演练:扩展服务器资源管理器以显示 Web 部件创建的扩展。本演练使用 SharePoint 服务器对象模型,但是,本演练通过使用客户端对象模型,来完成相同的任务。

系统必备

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

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

  • 使用 SharePoint 客户端对象模型。有关更多信息,请参见 Managed Client Object Model(托管客户端对象模型)。

  • 在 SharePoint 的 Web 部件。有关更多信息,请参见 Web Parts Overview(Web 部件概述)。

创建项目

若要完成本演练,您必须创建以下两个项目:

  • VSIX 项目创建 VSIX包以部署**“服务器资源管理器”**扩展。

  • 实现**“服务器资源管理器”**扩展的类库项目。

从创建项目开始本演练。

创建 VSIX 项目

  1. 启动 Visual Studio。

  2. 在菜单栏上,选择**“文件”“新建**、“项目”

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

    说明说明

    只有在安装 Visual Studio SDK,扩展性 节点可用。有关更多信息,请参见本主题前面的系统必备部分。

  4. 在对话框顶部,选择在 .NET Framework 的版本列表的 .NET Framework 4.5

    SharePoint 工具扩展需要在 .NET Framework 的这一版本的功能。

  5. 选择 VSIX 项目 模板。

  6. 名称 框中,键入 WebPartNode,然后选择 确定 按钮。

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

创建扩展项目

  1. 解决方案资源管理器,请打开解决方案节点的快捷菜单上,选择 添加,然后选择 新建项目

    说明说明

    在 Visual Basic 项目中,仅当在General, Projects and Solutions, Options Dialog Box中选中“总是显示解决方案”复选框时,解决方案节点才会出现在“解决方案资源管理器”中。

  2. 新建项目 对话框中,展开 visual C#Visual Basic 节点,然后选择 Windows

  3. 在对话框顶部,选择在 .NET Framework 的版本列表的 .NET Framework 4.5

  4. 在项目模板列表中,选择 类库

  5. 名称 框中,输入 WebPartNodeExtension,然后选择 确定 按钮。

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

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

配置扩展项目

在创建扩展编写代码,您必须先添加代码文件和程序集引用添加到项目,因此,您必须更新默认命名空间。

配置项目

  1. WebPartNodeExtension 项目中,添加名为 SiteNodeExtension 和 WebPartNodeTypeProvider 的两个代码文件。

  2. 打开 WebPartNodeExtension 项目的快捷菜单,然后选择 添加引用

  3. 引用管理器– WebPartNodeExtension 对话框中,选择 框架 节点,为 System.ComponentModel.Composition 和 System.Windows.Forms 程序集的然后选中复选框。

  4. 选择 扩展 节点,以下程序集中的每个复选框,然后选择 确定 按钮:

    • Microsoft.SharePoint.Client

    • Microsoft.SharePoint.Client.Runtime

    • Microsoft.VisualStudio.SharePoint

  5. 打开 WebPartNodeExtension 项目的快捷菜单,然后选择 属性

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

  6. 选择 应用程序 选项。

  7. 默认命名空间 框 (C#) 或 根命名空间 框 (Visual Basic) 中,输入 ServerExplorer.SharePointConnections.WebPartNode。

为新节点创建图标

创建 服务器资源管理器 扩展的两个图标:新 Web 部件库 节点的图标和每个子 Web 的另一个图标部件节点。Web 部件库 节点下。在本演练中,您将关联这些图标与节点的代码。

为节点创建图标

  1. 在 WebPartNodeExtension 项目的 项目设计器,选择 资源 选项。

  2. 选择 此项目中不包含默认资源文件链接。单击此处创建一个资源文件。”

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

  3. 在设计器的顶部,选择。添加资源 菜单命令的箭头,然后选择 添加新图标

  4. 新图标名称的 Enter WebPartsNode,然后选择 添加 按钮。

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

  5. 编辑 16x16 版本的图标,使其具有您可以轻松地识别的设计。

  6. 打开 32x32 版本的快捷菜单,然后选择 删除图像类型

  7. 重复添加第二个图标的第 3 步到第 7 步到项目资源,并将此图标 WebPart。

  8. 解决方案资源管理器,在 WebPartNodeExtension 项目的 资源 文件夹,选择 WebPartsNode.ico

  9. 属性 窗口中,打开 生成操作 列表,然后选择 嵌入的资源

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

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

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

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

  • 将下面的代码粘贴到 WebPartNodeExtension 项目的 SiteNodeExtension 代码文件。

    说明说明

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

    Imports System.Collections.Generic
    Imports System.ComponentModel.Composition
    Imports Microsoft.SharePoint.Client
    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: Indicates that this class extends SharePoint site nodes in Server Explorer.
        ' SiteNodeExtension class: Represents an extension of SharePoint site nodes in Server Explorer.
        <Export(GetType(IExplorerNodeTypeExtension))> _
        <ExplorerNodeType(ExplorerNodeTypes.SiteNode)> _
        Friend Class SiteNodeExtension
            Implements IExplorerNodeTypeExtension
    
            Private siteUrl As System.Uri = Nothing
    
            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)
    
                ' Get the site URL so that it can be used later to access the site
                ' by using the SharePoint client object model.
                siteUrl = e.Node.Context.SiteUrl
    
                ' 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 individual Web Part nodes under the new Web Part Gallery node.
            Private Sub CreateWebPartNodes(ByVal parentNode As IExplorerNode)
    
                ' Use the SharePoint client object model to get items from the Web Part gallery.
                Dim Context As ClientContext = New ClientContext(siteUrl.AbsoluteUri)
                Dim WebPartsGallery As List = Context.Web.GetCatalog(CType(ListTemplateType.WebPartCatalog, Integer))
                Dim WebParts As ListItemCollection = WebPartsGallery.GetItems(New CamlQuery())
    
                ' Request the FieldValuesAsText property values with the Web Part items.
                Context.Load(WebParts, Function(listItems) listItems.Include(Function(i) i.FieldValuesAsText))
                Context.ExecuteQuery()
    
                If WebParts IsNot Nothing Then
                    For Each WebPart As ListItem 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(ListItem), WebPart)
    
                        ' Create the new node for the current Web Part item.
                        parentNode.ChildNodes.Add(WebPartNodeTypeProvider.WebPartNodeTypeId, _
                            WebPart.FieldValuesAsText.FieldValues("Title"), Annotations)
                    Next
                End If
            End Sub
        End Class
    End Namespace
    
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using Microsoft.SharePoint.Client;
    using Microsoft.VisualStudio.SharePoint;
    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
        {
            private System.Uri siteUrl = null;
    
            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)
            {
                // Get the site URL so that it can be used later to access the site
                // by using the SharePoint client object model.
                siteUrl = e.Node.Context.SiteUrl;
    
                // 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 individual Web Part nodes under the new Web Part Gallery node.
            private void CreateWebPartNodes(IExplorerNode parentNode)
            {
                // Use the SharePoint client object model to get items from the Web Part gallery.
                ClientContext context = new ClientContext(siteUrl.AbsoluteUri);
                List webPartsGallery = context.Web.GetCatalog((int)ListTemplateType.WebPartCatalog);
                ListItemCollection webParts = webPartsGallery.GetItems(new CamlQuery());
    
                // Request the FieldValuesAsText property values with the Web Part items.
                context.Load(webParts, listItems => listItems.Include(i => i.FieldValuesAsText));
                context.ExecuteQuery();
    
                if (webParts != null)
                {
                    foreach (ListItem 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(ListItem), webPart } 
                        };
    
                        // Create the new node for the current Web Part item.
                        parentNode.ChildNodes.Add(WebPartNodeTypeProvider.WebPartNodeTypeId,
                            webPart.FieldValuesAsText.FieldValues["Title"], annotations);
                    }
                }
            }
        }
    }
    

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

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

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

定义 Web 部件节点类型

  • 将下面的代码粘贴到 WebPartNodeExtension 项目的 WebPartNodeTypeProvider 代码文件。

    Imports System
    Imports System.Collections.Generic
    Imports System.Windows.Forms
    Imports System.ComponentModel.Composition
    Imports Microsoft.SharePoint.Client
    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
                AddHandler typeDefinition.NodeMenuItemsRequested, AddressOf NodeMenuItemsRequested
            End Sub
    
            ' Retrieves properties that are displayed in the Properties window when
            ' a Web Part node is selected.
            Private Sub NodePropertiesRequested(ByVal Sender As Object, _
                ByVal e As ExplorerNodePropertiesRequestedEventArgs)
    
                Dim webPart = e.Node.Annotations.GetValue(Of ListItem)()
                Dim propertySource = e.Node.Context.CreatePropertySourceObject( _
                    webPart.FieldValuesAsText.FieldValues)
                e.PropertySources.Add(propertySource)
            End Sub
    
            Private Sub NodeMenuItemsRequested(ByVal Sender As Object, _
                ByVal e As ExplorerNodeMenuItemsRequestedEventArgs)
                Dim WebPartNodeMenuItem As IMenuItem = e.MenuItems.Add("Display Message")
                AddHandler WebPartNodeMenuItem.Click, AddressOf MenuItemClick
            End Sub
    
            Private Sub MenuItemClick(ByVal Sender As Object, ByVal e As MenuItemEventArgs)
                Dim ParentNode As IExplorerNode = TryCast(e.Owner, IExplorerNode)
                If ParentNode IsNot Nothing Then
                    Dim webPart = ParentNode.Annotations.GetValue(Of ListItem)()
                    MessageBox.Show("You clicked the context menu for the following Web part: " & _
                        webPart.FieldValuesAsText.FieldValues("Title") + ".", "Web Part Menu Command")
                End If
            End Sub
        End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.ComponentModel.Composition;
    using Microsoft.SharePoint.Client;
    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;
                typeDefinition.NodeMenuItemsRequested += NodeMenuItemsRequested;
            }
    
            // Retrieves properties that are displayed in the Properties window when
            // a Web Part node is selected.
            private void NodePropertiesRequested(object sender,
                ExplorerNodePropertiesRequestedEventArgs e)
            {
                var webPart = e.Node.Annotations.GetValue<ListItem>();
                object propertySource = e.Node.Context.CreatePropertySourceObject(
                    webPart.FieldValuesAsText.FieldValues);
                e.PropertySources.Add(propertySource);
            }
    
            private void NodeMenuItemsRequested(
                object sender, ExplorerNodeMenuItemsRequestedEventArgs e)
            {
                e.MenuItems.Add("Display Message").Click += MenuItemClick;
            }
    
            private void MenuItemClick(object sender, MenuItemEventArgs e)
            {
                IExplorerNode parentNode = e.Owner as IExplorerNode;
    
                if (parentNode != null)
                {
                    var webPart = parentNode.Annotations.GetValue<ListItem>();
                    MessageBox.Show("You clicked the context menu for the following Web part: " +
                        webPart.FieldValuesAsText.FieldValues["Title"] + ".", "Web Part Menu Command");
                }
            }
        }
    }
    

检查点

演练进行到此时,**“Web 部件库”**节点的所有代码都位于项目中。生成 WebPartNodeExtension 项目,以确保它在编译时不会出错。

生成项目

  • 解决方案资源管理器,打开 WebPartNodeExtension 项目的快捷菜单,然后选择 Build

创建 VSIX 包以部署扩展

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

配置 VSIX 包

  1. 解决方案资源管理器,在 WebPartNode 项目中,打开在清单编辑器中 source.extension.vsixmanifest 文件。

    source.extension.vsixmanifest 文件是所有 VSIX 包必需的 extension.vsixmanifest 文件的基础。有关此文件的更多信息,请参见VSIX 扩展架构参考

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

  3. 作者 框中,输入 Contoso。

  4. 说明 框中,输入 添加自定义 Web 部件库节点到在服务器资源管理器中的" SharePoint 连接"节点。

  5. 在编辑器中 资产 选项卡中,选择 新建 按钮。

  6. 添加新资产 对话框中,在 类型 列表中,选择 Microsoft.VisualStudio.MefComponent

    说明说明

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

  7. 列表中,选择 当前解决方案中的项目

  8. 项目 列表中,选择 WebPartNodeExtension,然后选择 确定 按钮。

  9. 在菜单栏上,依次选择 Build生成解决方案,然后确保解决方案已生成且未发生错误。

  10. 确保 WebPartNode 项目的生成输出文件夹现在包含 WebPartNode.vsix 文件。

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

测试扩展

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

开始调试扩展

  1. 重新启动使用管理凭据的 Visual Studio,然后打开 WebPartNode 解决方案。

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

  3. 选择 F5 键开始调试。

    Visual Studio 将扩展安装到 %UserProfile% \ AppData \ local \ Microsoft \ VisualStudio \ 11.0Exp \ extensions \ Contoso \ Web 部件库节点扩展服务器资源管理器\ 1.0 中并启动 Visual Studio 的实验实例。在此 Visual Studio 实例中测试项目项。

测试扩展

  1. 在 Visual Studio 的实验实例中,在菜单栏上,依次选择 视图服务器资源管理器

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

    1. 打开 SharePoint 连接的快捷菜单,然后选择 添加连接

    2. 添加 SharePoint 连接 对话框中,输入要连接到的 SharePoint 网站的 URL,然后选择 确定 按钮。

      若要指定开发计算机上的 SharePoint 网站,请键入 https://localhost。

  3. 展开显示网站的 URL 的节点) (,然后展开子网站节点 (例如,团队网站)。

  4. 验证另一个 Visual Studio 实例的代码在 NodeChildrenRequested 方法设置的断点处停止,然后选择 F5 键继续调试项目。

  5. 在 Visual Studio 的实验实例中,展开 Web 部件库 节点,该节点显示在首要网站节点下。

  6. 验证另一个 Visual Studio 实例的代码在 CreateWebPartNodes 方法设置的断点处停止,然后选择 F5 键继续调试项目。

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

  8. 打开 Web 部件的快捷菜单,然后选择 属性

  9. 属性 窗口,请验证有关 Web 部件的详细信息显示。

  10. 服务器资源管理器,打开同一个 Web 部件的快捷菜单,然后选择 显示消息

    在出现的消息框中,选择 确定 按钮。

从 Visual Studio 中卸载扩展

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

卸载扩展

  1. 在 Visual Studio 的实验实例中,在菜单栏上,依次选择 工具扩展和更新

    扩展和更新 对话框打开。

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

  3. 在出现的对话框中,选择 按钮。

  4. 选择 立即重新启动 按钮来卸载。

    相应的项目项也会随之卸载。

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

请参见

任务

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

创建图标或其他图像(图标的图像编辑器)

参考

图标的图像编辑器

概念

调入 SharePoint 对象模型

其他资源

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