演练:在 SharePoint Foundation 中创建可连接 Web 部件

上次修改时间: 2011年9月29日

适用范围: SharePoint Foundation 2010

本文内容
关于可连接的 Web 部件
创建实现 ICellProvider 接口的 Web 部件
步骤 1:创建接口类
步骤 2:声明事件
步骤 3:重写 EnsureInterfaces 方法,然后调用 RegisterInterface 方法
步骤 4:重写 CanRunAt 方法
步骤 5:重写 PartCommunicationConnect 方法
步骤 6:重写 PartCommunicationInit 方法
步骤 7:重写 PartCommunicationMain 方法
步骤 8:重写 GetInitEventArgs 方法
步骤 9:实现接口事件处理程序
步骤 10:重写 RenderWebPart 方法
步骤 11:实现支持的方法
一对实现 ICellProvider 和 ICellConsumer 接口的示例 Web 部件

此编程任务描述如何创建两个可连接的 SharePoint Web 部件:一个可使用单个单元格值的 Web 部件和一个可提供单个单元格值的 Web 部件。

重要注释重要信息

Microsoft SharePoint Foundation 中的 Web 部件基础结构是在 Microsoft ASP.NET Web 部件基础结构的基础上构建的,并且 SharePoint 完全支持派生自 ASP.NETWebPart 类的 Web 部件(包括 ASP.NET 连接模型)。只要有可能,就应创建 ASP.NET Web 部件,并使用 ASP.NET 连接模型连接 Web 部件。

有关选择从中派生的最佳 WebPart 基类的详细信息,请参阅Creating Web Parts in Windows SharePoint Services。有关 ASP.NET Web 部件及其连接模型的详细信息,请参阅 ASP.NET 文档中的 Web 部件连接概述

关于可连接的 Web 部件

SharePoint Web 部件基础结构提供一组称为"连接接口"的标准化接口,利用这些接口,Web 部件可在运行时相互交换信息。例如,在 SharePoint Foundation 中构建的列表 Web 部件可以为任何其他可以使用(接收)数据行的 Web 部件提供(发送)该数据行,例如,实现用于显示行的表单的 Web 部件。

由于 Web 部件基础结构提供了一组标准连接接口,因此可连接的 Web 部件可以完全由不同的开发人员或公司进行开发以便彼此进行通信。最终用户可将支持连接接口的 Web 部件与 Microsoft SharePoint Designer 或 Web 浏览器连接。这将允许最终用户通过简单的菜单驱动用户界面来生成复杂的 Web 部件组合。

SharePoint Foundation 连接类和接口是在 Microsoft.SharePoint.WebPartPages.Communication 命名空间中实现的。

连接接口

连接接口是与特定项目相关的成对事件,例如列表中的行。成对接口在实现它们的 Web 部件之间形成一个通信总线。可连接的 Web 部件将引发针对一个或多个已连接的部件的接口事件,从而使其执行操作。接口是作为针对使用者的提供程序成对出现的。来自提供程序的事件由使用者处理,反之亦然。下表简要描述了每对连接接口。

连接接口对

说明

ICellProviderICellConsumer

用于提供或使用单值项目(例如一个单元格或字段)的连接接口。

IRowProviderIRowConsumer

用于提供或使用单行(或多行)值的连接接口。

IListProviderIListConsumer

用于提供或使用整个列表的连接接口。

IFilterProviderIFilterConsumer

用于提供或使用筛选值的连接接口。例如,SharePoint 列表 Web 部件支持 IListProviderIRowProviderIFilterConsumer。由于 IRowProvider 可以连接到 IFilterConsumer,因此可以将两个不同的 SharePoint 列表彼此连接。这样,其中的一个列表就可以筛选另一个连接的列表。

IParametersInProviderIParametersInConsumer

IParameterIn 接口允许传递和接收 Web 部件之间的任意参数的任何组。这些接口可用于处理使用者 Web 部件拥有参数列表并需要将其与其他 Web 部件进行通信的情况。

IParametersOutProviderIParametersOutConsumer

IParameterOut 接口允许传递和接收 Web 部件之间的任意参数的任何组。这些接口可用于处理提供程序 Web 部件拥有参数列表并需要将其与其他 Web 部件进行通信的情况。

兼容性规则

仅在 Web 部件兼容的情况下,才能连接这些部件。以下是几条兼容性规则,这些规则是在确定两个 Web 部件是否可以连接时由 Web 部件基础结构评定的。如果发现 Web 部件不兼容,则浏览器中的"连接"菜单项将处于禁用状态,并会出现一个工具提示,以解释不兼容的原因。

相反的对

连接接口只能与其他兼容的接口连接。最基本的兼容性规则是接口必须作为相反的对连接或通过转换器连接。作为相反的对连接意味着实现 IRowProvider 接口的 Web 部件可以与实现 IRowConsumer 接口的另一个部件连接。

转换器

在一个 Web 部件需要连接到另一个接口不完全相同的部件的情况下,Web 部件基础结构将提供接口转换器,它有助于用户通过自然而明晰的方式连接两个不同的接口。

例如,用户可能希望将联系人列表连接到图片查看器。但是,联系人列表只有 IRowProvider 接口,而图片查看器只有 ICellConsumer 接口。为了解决此问题,将提供一个可用于将这两个接口彼此连接的接口转换器。

下表显示可通过转换器彼此连接的接口对以及连接是否需要 Microsoft SharePoint Designer 2010。

转换器

在浏览器中

连接

在 SharePoint Designer 2010 中连接

IRowProviderICellConsumer

IRowProviderIFilterConsumer

IParametersOutProviderIParametersInConsumer

IRowProviderIParametersInConsumer

跨页连接

允许将一些接口连接到不同页面上的 Web 部件。此行为与超链接类似。

应了解有关跨页连接的以下信息:

  • 与 SharePoint Foundation 兼容的网页编辑器(例如,SharePoint Designer 2010)是创建跨页连接所必需的。不过,一旦形成跨页连接,则任何受支持的 Web 浏览器均可以在运行时使用该连接。

  • 只有具有设计为在服务器上运行的实现(CanRunAt 方法具有一个 Server 或 ServerAndClient 的 ConnectionRunAt 值)的可连接 Web 部件可建立跨页连接。不允许客户端上形成的连接跨网页。

下表演示可跨页连接的接口。

源页接口

目标页接口

IRowProvider

IFilterConsumer

IRowProvider

IParametersInConsumer

IFilterProvider

IFilterConsumer

IParametersOutProvider

IParametersInConsumer

IParametersInProvider

IParametersInConsumer

在使用跨页 Web 部件连接时,必须执行以下操作:

客户端和服务器连接

在任何给定时间,都允许在客户端或服务器上运行 Web 部件。一些 Web 部件(如果根据情况进行设计)可以检测其运行条件并动态切换为在客户端或服务器上运行。只能将 Web 部件连接到在相同位置上运行的其他 Web 部件。例如,只能将服务器端部件连接到其他服务器端部件。不能将服务器端部件连接到客户端部件。连接链必须是同源的。如果某个部件可以在客户端或服务器连接之间动态切换,则 Web 部件基础结构会自动将此 Web 部件固定为客户端部件或服务器端部件,具体取决于此 Web 部件所连接到的 Web 部件链。

最大连接数

在对接口进行注册时,可以在 RegisterInterface 方法的 maxConnections 参数中指定针对其他 Web 部件的最大连接数。如果在某个 Web 部件上超出了连接限制,则不能将此部件连接到其他部件。

选项为 1 或无限制。

无循环连接

Web 部件不能直接或通过连接链来自我连接。

共享的和专用的 Web 部件连接

共享的 Web 部件可以连接到专用 Web 部件,如果专用 Web 部件是一个使用者且共享的 Web 部件支持无数连接。

程序流

连接的 Web 部件通过触发特定的接口事件来彼此传递信息。当 Web 部件实现接口(例如,ICellProvider)时,它必须重写大量方法。接口事件的触发操作由在指定时间调入到已重写的方法内的 Web 部件基础结构执行。以下用于创建可连接的 Web 部件的步骤定义需要重写的方法以及 Web 部件作者在执行此操作时应使用的典型代码。

创建实现 ICellProvider 接口的 Web 部件

此编程任务定义创建类的过程,该类为使用 ICellProvider 接口的连接接口实现所有必需的方法和事件。有关完整的代码示例,请参阅这些步骤结尾的 ICellProviderICellConsumer 源代码示例。

下面是 11 个高级步骤,若要实现 Web 部件的连接接口,则必须完成这些步骤:

  1. 创建接口类。

  2. 声明事件。

  3. 重写 EnsureInterfaces 方法,然后调用 RegisterInterface 方法。

  4. 重写 CanRunAt 方法。

  5. 重写 PartCommunicationConnect 方法。

  6. 重写 PartCommunicationInit 方法。

  7. 重写 PartCommunicationMain 方法。

  8. 重写 GetInitEventArgs 方法。

  9. 实现接口事件处理程序。

  10. 重写 RenderWebPart 方法。

  11. 实现支持的方法。

步骤 1:创建接口类

创建实现预定义的连接接口之一的类。在此示例中,将实现 ICellProvider 接口。对于剩余步骤 (2-11),所有代码都包含在此类中。

示例

public class CellProvider : WebPart, ICellProvider

{
       // Much code goes here. See steps 2 – 11.
}
Public Class CellProvider
    Inherits WebPart
    Implements ICellProvider

    ' Much code goes here. See steps 2 – 11.
End Class

步骤 2:声明事件

声明连接接口的所有相关事件。在此位置上,还声明 Web 部件使用的其他变量。由于正在使用 ICellProvider 接口,因此下面的示例将声明其 CellProviderInitCellReady 事件的变量。

示例

// CellProviderInit Event

public event CellProviderInitEventHandler CellProviderInit;

// CellReady Event

public event CellReadyEventHandler CellReady;
' CellProviderInit Event

Public Event CellProviderInit As CellProviderInitEventHandler

' CellReady Event

Public Event CellReady As CellReadyEventHandler

步骤 3:重写 EnsureInterfaces 方法,然后调用 RegisterInterface 方法

重写 EnsureInterfaces 方法。此方法在 Web 部件呈现之前由 Web 部件基础结构调用,同时 Web 部件应通过调用两种 RegisterInterface 方法之一来为其所有接口注册。

示例

public override void EnsureInterfaces()
{
   // Register Interfaces      (See following section) 

}
Public Overrides Sub EnsureInterfaces()
   ' Register Interfaces      (See following section) 

End Sub

在重写的 EnsureInterfaces 方法内,应告知 Web 部件基础结构将通过调用 RegisterInterface 方法来使用接口。如步骤 3 中所述,RegisterInterface 方法出现在 EnsureInterfaces 方法中。RegisterInterface 方法将使用下面定义的几个参数。

方法定义

protected InterfaceProperties RegisterInterface(string interfaceName,
                     string interfaceType,
                     int maxConnections,
                     ConnectionRunAt runAtOptions,
                     object interfaceObject,
                     string interfaceClientReference,
                     string menuLabel,
                     string description)
 Protected Function RegisterInterface(ByVal interfaceName As String,
                                         ByVal interfaceType As String,
                                         ByVal maxConnections As Integer,
                                          ByVal runAtOptions As ConnectionRunAt,
                                          ByVal interfaceObject As Object,
                                          ByVal interfaceClientReference As String,
                                          ByVal menuLabel As String,
                                          ByVal description As String) As InterfaceProperties

End Function

备注

第二个 RegisterInterface 方法可用,此方法将提供一个用于显式指定接口是否支持跨页连接的附加 allowCrossPageConnection 参数。不包含此参数的 RegisterInterface 方法会为由 Web 部件基础结构定义的连接兼容性规则支持的所有连接接口(请参阅本主题中前面的"跨页连接")将 allowCrossPageConnection 参数的设置硬编码为 true。所有其他连接接口将硬编码为 false。

方法参数

参数

说明

interfaceName

一个字符串属性,它是接口的友好名称。友好名称在部件内应是唯一的。此属性不能包含以下特殊字符:<、>、&、双引号、单引号、逗号或分号。

interfaceType

一个表示接口的类型(IRowProviderICellConsumer 等)的属性。

maxConnections

一个属性,Web 部件基础结构可以查询此属性以确定可在给定接口上形成的连接的数目。maxConnections 是一个 int。它可以具有 WebPart.LimitOneConnectionWebPart.UnlimitedConnections 的值。

runAtOptions

定义可运行接口的位置(Client、Server、ClientAndServer、None)。

interfaceObject

一个对实现此接口的实际对象的引用。

interfaceClientReference

对于客户端连接,interfaceClientReference 是一个用作实现该接口的客户端对象的标识符的字符串。此标识符应包含一个 _WPQ_ 以确保该名称的唯一性,并且还可以包含诸如 () 之类的特殊字符。如果部件不支持客户端通信,则可以使用空字符串。Web 部件基础结构会将双引号作为单引号进行编码。

备注

WPQ_ 是一个标记,在呈现部件时,Web 部件结构会将此标记替换为唯一标识符。

menuLabel

接口的常规标签或说明。这将在连接菜单用户界面中出现。建议您使用诸如"Provide"或"Consume"之类的动词来启动菜单标签,以便用户创建一个了解数据流方向的连接。

description

接口的扩展说明。

示例

InterfaceProperties myCellProviderInterface = RegisterInterface(
   "MyCellProviderInterface_WPQ_",   //InterfaceName 
   "ICellProvider",         //InterfaceType 
   WebPart.UnlimitedConnections,   //MaxConnections 
   ConnectionRunAt.ServerAndClient,   //RunAtOptions 
   this,               //InterfaceObject 
   "CellProviderInterface_WPQ_",   //InterfaceClientReference 
   "Provide Value From Text Box",         //MenuLabel 
   "Provides the value entered into the text box.");   //Description
Dim myCellProviderInterface As InterfaceProperties = RegisterInterface("MyCellProviderInterface_WPQ_", "ICellProvider", WebPart.UnlimitedConnections, ConnectionRunAt.ServerAndClient, Me, "CellProviderInterface_WPQ_", "Provide Value From Text Box", "Provides the value entered into the text box.") 'Description

备注

若要捕获代码访问安全权限异常,请在 try/catch 块中包含 RegisterInterface 调用。有关如何执行此操作的示例,请参阅 RegisterInterface 方法主题。

步骤 4:重写 CanRunAt 方法

所有可连接的 Web 部件都必须重写 CanRunAt 方法。Web 部件基础结构将调用此方法以确定是可以在服务器、客户端还是两者上运行 Web 部件。Web 部件必须基于用户客户端的当前配置和它连接到的其他 Web 部件来确定它可运行的位置。它可以返回以下 ConnectionRunAt 枚举值:Client、Server、ClientAndServer 和 None。例如,Web 部件可以具有两种不同的呈现:丰富呈现和下层呈现。Web 部件可能需要为其丰富呈现安装 ActiveX 组件。在此情况下,如果安装 ActiveX 组件,则 CanRunAt 方法将返回 Client;否则将返回 Server。

示例

public override ConnectionRunAt CanRunAt()
{
   // This Web Part can run on both the client and the server
   return ConnectionRunAt.ServerAndClient;
}
public override ConnectionRunAt CanRunAt()
{
   // This Web Part can run on both the client and the server
   return ConnectionRunAt.ServerAndClient;
}

步骤 5:重写 PartCommunicationConnect 方法

所有可连接的 Web 部件都必须重写 PartCommunicationConnect 方法。Web 部件基础结构将调用此方法以告知 Web 部件其已连接,并传递与其连接到的部件相关的信息。只要 Web 部件基础结构与连接的相应事件链接在一起,就会出现此情况。在此方法中,Web 部件作者应跟踪可运行该接口的位置,创建所需的任何用户界面控件,并验证连接是否正确形成。此方法具有下面定义的几个参数。

方法定义

public override void PartCommunicationConnect (string interfaceName, 
                  WebPart connectedPart, 
                  string connectedInterfaceName, 
                  ConnectionRunAt runAt)
Public Overrides Sub PartCommunicationConnect(ByVal interfaceName As String, ByVal connectedPart As WebPart, ByVal connectedInterfaceName As String, ByVal runAt As ConnectionRunAt)

End Sub

方法参数

参数

说明

interfaceName

将连接的接口的友好名称。

connectedPart

对要连接到的另一个 Web 部件的引用。connectedPart 和 connectedInterfaceName 参数提供一种用于连接部件以标识其正在连接到的部件的类型的方式。这可让 Web 部件建立与另一个部件更合理的交互。例如,如果源部件包含有关目标部件的详细信息,则源部件可以接进目标部件的公共对象模型。但是,必须按此意图设计这两个部件才能使其正常工作。例如,可将图表部件和透视表部件设计为在连接时共享同一公共数据源布局。

connectedInterfaceName

通过其连接的其他 Web 部件上的接口的友好名称。

runAt

可执行接口的位置。此位置将为客户端或服务器并由 Web 部件基础结构基于几个因素来确定。

示例

public override void PartCommunicationConnect(string interfaceName,
   WebPart connectedPart,
   string connectedInterfaceName,
   ConnectionRunAt runAt)
{
   // Check to see if this is a client-side part
   if (runAt == ConnectionRunAt.Client)
   {
      // This is a client-side part
      _runAtClient = true;
      return;
   }

   // Must be a server-side part - create the Web Part's controls
   EnsureChildControls(); 

   // Check if this is my particular cell interface
   if (interfaceName == "MyCellProviderInterface_WPQ_")
   {
      // Keep a count of the connections
   _cellConnectedCount++;
   }
}
Public Overrides Sub PartCommunicationConnect(ByVal interfaceName As String, ByVal connectedPart As WebPart, ByVal connectedInterfaceName As String, ByVal runAt As ConnectionRunAt)
   ' Check to see if this is a client-side part
   If runAt Is ConnectionRunAt.Client Then
       ' This is a client-side part
       _runAtClient = True
        Return
   End If

   ' Must be a server-side part - create the Web Part's controls
   EnsureChildControls()

   ' Check if this is my particular cell interface
   If interfaceName = "MyCellProviderInterface_WPQ_" Then
      ' Keep a count of the connections
      _cellConnectedCount += 1
   End If
End Sub

步骤 6:重写 PartCommunicationInit 方法

可连接的 Web 部件可以选择重写 PartCommunicationInit 方法。Web 部件基础结构调用此方法以允许 Web 部件触发任何初始化事件。Web 部件应触发以"Init"结尾的任何事件(例如,CellProviderInit)。

当 Web 部件需要向其他部件公开有关其自身的一些信息时,Init 参数将很有用。例如,当列表部件连接到表单部件时,列表部件可以公开将其字段名。然后,表单部件可以基于来自列表部件的字段名呈现其用户界面。

示例

备注

对于客户端 Web 部件,必须在客户端上实现此事件及其事件处理程序。

public override void PartCommunicationInit()
{
   //If the connection wasn't formed then don't send Init event
   if(_cellConnectedCount > 0)
   {
      //If there is a listener, send Init event
      if (CellProviderInit != null)
      {
         //Need to create the args for the CellProviderInit event
         CellProviderInitEventArgs cellProviderInitEventArgs = new
         CellProviderInitEventArgs();

         //Set the FieldName
         cellProviderInitEventArgs.FieldName = _cellName;
         cellProviderInitEventArgs.FieldDisplayName = _cellDisplayName;

         //Fire the CellProviderInit event
         CellProviderInit(this, cellProviderInitEventArgs);
      }
   }
}
Public Overrides Sub PartCommunicationInit()
    'If the connection wasn't formed then don't send Init event
    If _cellConnectedCount > 0 Then
        'If there is a listener, send Init event
        If CellProviderInit IsNot Nothing Then
            'Need to create the args for the CellProviderInit event
            Dim cellProviderInitEventArgs As New CellProviderInitEventArgs()

            'Set the FieldName
            cellProviderInitEventArgs.FieldName = _cellName
            cellProviderInitEventArgs.FieldDisplayName = _cellDisplayName

            'Fire the CellProviderInit event
            CellProviderInit(Me, cellProviderInitEventArgs)
        End If
    End If
End Sub

步骤 7:重写 PartCommunicationMain 方法

可连接的 Web 部件可以选择重写 PartCommunicationMain 方法。Web 部件基础结构调用此方法以允许 Web 部件触发来自接口的任何其他事件(例如,CellReady)。在执行 PartCommunicationMain 方法的过程中,数据值的实际通信(相对于架构)将在 Web 部件之间进行。

示例

备注

对于客户端 Web 部件,必须在客户端上实现此事件及其事件处理程序。

public override void PartCommunicationMain()

{
   // NOTE: THIS CODE IS SPECIFIC TO EACH AND EVERY WEB PART’S IMPLEMENTATION.
   // If the connection wasn't formed then don't send Ready event
   if(_cellConnectedCount > 0)
   {
      // If there is a listener, send CellReady event
      if (CellReady != null)
      {
         // Need to create the args for the CellProviderInit event
         CellReadyEventArgs cellReadyEventArgs = new CellReadyEventArgs();

         // If user clicked button then send the value
         if (_cellClicked)
         {
            // Set the Cell to the value of the TextBox text
            // This is the value that will be sent to the Consumer
            cellReadyEventArgs.Cell = _cellInput.Text;
         }

         else
         {
            // The user didn't actually click the button
            // so just send an empty string to the Consumer
            cellReadyEventArgs.Cell = "";
         }

         // Fire the CellReady event
         // The Consumer will then receive the Cell value
         CellReady(this, cellReadyEventArgs);
      }
   }
}
 Public Overrides Sub PartCommunicationMain()

    ' NOTE: THIS CODE IS SPECIFIC TO EACH AND EVERY WEB PART’S IMPLEMENTATION.
    ' If the connection wasn't formed then don't send Ready event
    If _cellConnectedCount > 0 Then
        ' If there is a listener, send CellReady event
        If CellReady IsNot Nothing Then
            ' Need to create the args for the CellProviderInit event
            Dim cellReadyEventArgs As New CellReadyEventArgs()

            ' If user clicked button then send the value
            If _cellClicked Then
                ' Set the Cell to the value of the TextBox text
                ' This is the value that will be sent to the Consumer
                cellReadyEventArgs.Cell = _cellInput.Text

            Else
                ' The user didn't actually click the button
                ' so just send an empty string to the Consumer
                cellReadyEventArgs.Cell = ""
            End If

            ' Fire the CellReady event
            ' The Consumer will then receive the Cell value
            CellReady(Me, cellReadyEventArgs)
        End If
    End If
End Sub

步骤 8:重写 GetInitEventArgs 方法

如果需要,可连接的 Web 部件应重写 GetInitEventArgs 方法。GetInitEventArgs 方法仅对于使用转换器的接口是必需的。例如,IRowProviderICellConsumerIFilterConsumerIParametersOutProviderIParametersInConsumer 都可以支持转换器。对于创建转换器用户界面所需的所有初始数据,连接创作工具将调用 GetInitEventArgs 方法。此方法将返回 InitEventArgs 对象并接受接口名称。

例如,在连接两个支持 IRowProviderICellConsumer 接口的 Web 部件时,用户必须指定 IRowProvider Web 部件中的哪一个字段应映射到 ICellConsumer Web 部件中的输入值。Web 部件基础结构通过在每个接口上调用 GetInitEventArgs 方法来达到此目的。连接创作工具(如 SharePoint Designer)或浏览器使用已传递的 Init 参数来构建转换器的用户界面,此用户界面允许用户选择字段映射。

方法定义

public override InitEventArgs GetInitEventArgs(string interfaceName)
Public Overrides Function GetInitEventArgs(ByVal interfaceName As String) As InitEventArgs
End Function

方法参数

参数

说明

interfaceName

一个字符串属性,它是接口的友好名称。

示例

备注

可以在服务器或客户端上实现此方法。

重要注释重要信息

已将一个实现 ICellProvider 接口的 Web 部件的代码示例用作这些步骤中的示例。但是,ICellProvider 接口不应重写 GetInitEventArgs 方法,原因是它不能使用转换器。不过,为了完整起见,下面是一个来自位于此编程任务结尾的 CellConsumer.cs 代码示例的示例,此示例将重写 GetInitEventArgs 方法。

public override InitEventArgs GetInitEventArgs(string interfaceName)
{
   //Check if this is my particular cell interface
   if (interfaceName == "MyCellConsumerInterface_WPQ_")
   {
      EnsureChildControls();

      //Need to create the args for the CellConsumerInit event
      CellConsumerInitEventArgs cellConsumerInitArgs = 
         new CellConsumerInitEventArgs();

      //Set the FieldName and FieldDisplayName
      cellConsumerInitArgs.FieldName = _cellName;
      cellConsumerInitArgs.FieldDisplayName = _cellDisplayName;

      //return the InitArgs
      return(cellConsumerInitArgs);
   }
   else
   {
      return(null);
   }
}
Public Overrides Function GetInitEventArgs(ByVal interfaceName As String) As InitEventArgs
    'Check if this is my particular cell interface
    If interfaceName = "MyCellConsumerInterface_WPQ_" Then
        EnsureChildControls()

        'Need to create the args for the CellConsumerInit event
        Dim cellConsumerInitArgs As New CellConsumerInitEventArgs()

        'Set the FieldName and FieldDisplayName
        cellConsumerInitArgs.FieldName = _cellName
        cellConsumerInitArgs.FieldDisplayName = _cellDisplayName

        'return the InitArgs
        Return cellConsumerInitArgs
    Else
        Return Nothing
    End If
End Function

步骤 9:实现接口事件处理程序

基于要使用的接口的类型实现适当的事件处理程序。在此示例中,ICellProvider 接口必须实现 CellConsumerInitEventHandler 事件处理程序。不管是否使用由 ICellConsumer 接口传递的数据,都必须实现此事件处理程序。使用者部件将在其 PartCommunicationInit方法运行时触发此事件。

方法定义

public void CellConsumerInit(object sender, CellConsumerInitEventArgs cellConsumerInitEventArgs)

方法参数

参数

说明

sender

调用此方法的对象。

cellConsumerInitEventArgs

PartCommunicationInit 阶段由使用者 Web 部件传递的参数。

示例

public void CellConsumerInitEventHandler(object sender, CellConsumerInitEventArgs cellConsumerInitEventArgs)
{
   // This is where the Provider part could see what type of "Cell" 
   //  the Consumer was expecting/requesting.
   // For this simple code example, this information is not used
   // anywhere.

}
Public Sub CellConsumerInitEventHandler(ByVal sender As Object, ByVal cellConsumerInitEventArgs As CellConsumerInitEventArgs)
   ' This is where the Provider part could see what type of "Cell" 
   '  the Consumer was expecting/requesting.
   ' For this simple code example, this information is not used
   ' anywhere.

End Sub

步骤 10:重写 RenderWebPart 方法

所有 Web 部件都必须重写 RenderWebPart 方法。此详细信息特定于每一个 Web 部件。Web 部件基础结构调用此方法以呈现 Web 部件。有关完整示例,请参阅位于此编程任务主题结尾的 CellProvider.cs 源代码。为简洁起见,下面提供了一个框架示例。

示例

protected override void RenderWebPart(HtmlTextWriter output)
{
   // Need to ensure that all of the Web Part's controls are created
   EnsureChildControls();

   // Render client connection code if the connection is client-side
   if (_runAtClient)
   {
      // Script for client-side rendering
   }
   else
   {
      // If connected then display all cell child controls
      if (_cellConnectedCount > 0)
      {
         // Code for server-side rendering
      }

      else
      {
         // There wasn't a cell connection formed,
      }
   }
}
Protected Overrides Sub RenderWebPart(ByVal output As HtmlTextWriter)
    ' Need to ensure that all of the Web Part's controls are created
    EnsureChildControls()

    ' Render client connection code if the connection is client-side
    If _runAtClient Then
        ' Script for client-side rendering
    Else
        ' If connected then display all cell child controls
        If _cellConnectedCount > 0 Then
            ' Code for server-side rendering

        Else
            ' There wasn't a cell connection formed,
        End If
    End If
End Sub

步骤 11:实现支持的方法

应在 ICellProvider 源代码中的以下位置定义所有支持的方法。下面显示了一个框架。有关完整示例,请参阅位于此编程任务主题结尾的 CellProvider.cs 源代码。

示例

// Create all controls for this Web Part
protected override void CreateChildControls()
{
   //Code for Child Controls
}

// The Button OnClick event handler
private void CellButtonClicked(object sender, EventArgs e)
{
   _cellClicked = true; //user clicked button, set to true
}
' Create all controls for this Web Part
Protected Overrides Sub CreateChildControls()
   'Code for Child Controls
End Sub

' The Button OnClick event handler
Private Sub CellButtonClicked(ByVal sender As Object, ByVal e As EventArgs)
   _cellClicked = True 'user clicked button, set to true
End Sub

一对实现 ICellProvider 和 ICellConsumer 接口的示例 Web 部件

下面的两个代码示例阐释如何创建两个实现 ICellProviderICellConsumer 接口的可连接的 Web 部件。

若要完成此编程任务,请将下面的代码示例剪切并粘贴到 Web 部件项目的两个 C# 文件中,然后生成项目。

//--------------------------------------------------------------------
// File : CellProvider.cs
//
// Purpose : A sample connectable Web Part that implements the 
//          ICellProvider interface.
//
//---------------------------------------------------------------------

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.WebPartPages.Communication;
using System.Runtime.InteropServices;

namespace ICellDemo
{
   /// <summary>
   /// The CellProvider Web Part class implementes the ICellProvider 
   /// interface. Its UI is very basic - it displays a simple text 
   /// box and button.  The CellConsumer Web Part class implements 
   /// the ICellConsumer interface.  When the CellProvider is
   /// connected to the CellConsumer on a Web Part Page, the CellProvider 
   /// can pass the value in its text box to the CellConsumer which displays 
   /// the value inline.
   /// </summary>
   /// 

   //Step #1: Implement the Connection Interface (ICellProvider)
   public class CellProvider : WebPart, ICellProvider
   {
      //Step #2: Declare Connection Events
      public event CellProviderInitEventHandler CellProviderInit;
      public event CellReadyEventHandler CellReady;

      //Used to keep track of whether or not the connection will be running client-side
      private bool _runAtClient = false;

      //Keep a count of ICell connections
      private int _cellConnectedCount = 0;

      //Web Part UI
      private Button _cellButton;   
      private TextBox _cellInput;
      
      //Cell information
      private string _cellName;
      private string _cellDisplayName;

      //Used to keep track of whether or not the Button in the Web Part was clicked
      private bool _cellClicked = false;


      //Step #3: EnsureInterfaces
      //Notification to the Web Part that is should ensure that all
      //its interfaces are registered using RegisterInterface.
      public override void EnsureInterfaces()
      {
         //Registers an interface for the Web Part
         RegisterInterface("MyCellProviderInterface_WPQ_",  //InterfaceName
            InterfaceTypes.ICellProvider,               //InterfaceType
            WebPart.UnlimitedConnections,               //MaxConnections
            ConnectionRunAt.ServerAndClient,            //RunAtOptions
            this,                                 //InterfaceObject
            "CellProviderInterface_WPQ_",               //InterfaceClientReference
            "Provide String from Textbox",               //MenuLabel
            "Provides a Textbox string");               //Description
      }


      //Step #4: CanRunAt - called by framework to determine where a part can run.
      public override ConnectionRunAt CanRunAt()
      {
         //This Web Part can run on both the client and the server
         return ConnectionRunAt.ServerAndClient;
      }

      //Step #5: PartCommunicationConnect - Notification to the Web Part that it has been connected.
      public override void PartCommunicationConnect(string interfaceName,
         WebPart connectedPart,
         string connectedInterfaceName,
         ConnectionRunAt runAt)
      {
         //Check to see if this is a client-side part
         if (runAt == ConnectionRunAt.Client)
         {
            //This is a client-side part
            _runAtClient = true;
            return;
         }
         
         //Must be a server-side part so need to create the Web Part's controls
         EnsureChildControls(); 

         //Check if this is my particular cell interface
         if (interfaceName == "MyCellProviderInterface_WPQ_")
         {
            //Keep a count of the connections
            _cellConnectedCount++;
         }
      }

      //Step #6: PartCommunicationInit - Notification to the Web Part that it has been connected.
      public override void PartCommunicationInit()
      {
         //If the connection wasn't actually formed then don't want to send Init event
         if(_cellConnectedCount > 0)
         {
            //If there is a listener, send Init event
            if (CellProviderInit != null)
            {
               //Need to create the args for the CellProviderInit event
               CellProviderInitEventArgs cellProviderInitArgs = new CellProviderInitEventArgs();
               
               //Set the FieldName
               cellProviderInitArgs.FieldName = _cellName;
               cellProviderInitArgs.FieldDisplayName = _cellDisplayName;
               
               //Fire the CellProviderInit event.
               CellProviderInit(this, cellProviderInitArgs);
            }
         }
      }

      //Step #7: PartCommunicationMain - Called by the framework to allow part to fire any remaining events
      public override void PartCommunicationMain()
      {
         //If the connection wasn't actually formed then don't want to send Ready event
         if(_cellConnectedCount > 0)
         {
            //If there is a listener, send CellReady event
            if (CellReady != null)
            {
               //Need to create the args for the CellProviderInit event
               CellReadyEventArgs cellReadyArgs = new CellReadyEventArgs();

               //If user clicked button then send the value
               if (_cellClicked)
               {
                  //Set the Cell to the value of the TextBox text
                  //This is the value that will be sent to the Consumer
                  cellReadyArgs.Cell = _cellInput.Text;
               }
               else
               {
                  //The user didn't actually click the button
                  //so just send an empty string to the Consumer
                  cellReadyArgs.Cell = "";
               }

               
               //Fire the CellReady event.
               //The Consumer will then receive the Cell value
               CellReady(this, cellReadyArgs);
            }
         }
      }

      //Step #8: GetInitArgs is not needed in this case. GetInitEventArgs only needs to be
      //implemented for interfaces that can participate in a transformer which are 
      //the following: ICellConsumer, IRowProvider, IFilterConsumer, IParametersOutProvider, 
      //IParametersInConsumer
 
      //Step #9: Implement CellConsumerInit event handler.
      public void CellConsumerInit(object sender, CellConsumerInitEventArgs cellConsumerInitArgs)
      {
         //This is where the Provider part could see what type of "Cell" the Consumer
         //was expecting/requesting.
         //For this simple code example, this information is not used anywhere.
      }

      //Step #10: RenderWebPart - defines Web Part UI and behavior
      protected override void RenderWebPart(HtmlTextWriter output)
      {
         //Need to ensure that all of the Web Part's controls are created
         EnsureChildControls();

         //Render client connection code if the connection is client-side
         if (_runAtClient)
         {
            //Connected client-side
            output.Write(ReplaceTokens("<br><h5>Connected Client-Side</h5><br>\n"
               + "<input type=\"text\" id=\"CellInput_WPQ_\"/>\n"
               + "<button id=\"CellButton_WPQ_\" onclick=\"CellButtonOnClick_WPQ_()\">Fire CellReady</button>\n"
               + "<SCRIPT LANGUAGE=\"JavaScript\">\n"
               + "<!-- \n"
               + "    var CellProviderInterface_WPQ_ = new myCellProviderInterface_WPQ_();\n"

               + "    function myCellProviderInterface_WPQ_()\n"
               + "    {\n"
               + "        this.PartCommunicationInit = myInit;\n"
               + "        this.PartCommunicationMain = myMain;\n"
               + "        this.CellConsumerInit = myCellConsumerInit;\n"

               + "        function myInit()\n"
               + "        {\n"
               + "            var cellProviderInitArgs = new Object();\n"
               + "            cellProviderInitArgs.FieldName = \"CellName\";\n"

               + "            WPSC.RaiseConnectionEvent(\"MyCellProviderInterface_WPQ_\", \"CellProviderInit\", cellProviderInitArgs);\n"
               + "        }\n"

               + "        function myMain()\n"
               + "        {\n"
               + "            var cellReadyArgs = new Object();\n"
                    + "            cellReadyArgs.Cell = \"\";\n"

               + "            WPSC.RaiseConnectionEvent(\"MyCellProviderInterface_WPQ_\", \"CellReady\", cellReadyArgs);\n"
               + "        }\n"

               + "        function myCellConsumerInit(sender, cellConsumerInitArgs)\n"
               + "        {\n"
                + "        }\n"
               + "    }\n"

               + "    function CellButtonOnClick_WPQ_()\n"
               + "    {\n"
               + "        var cellReadyArgs = new Object();\n"
               + "        cellReadyArgs.Cell = document.all(\"CellInput_WPQ_\").value;\n"

               + "        WPSC.RaiseConnectionEvent(\"MyCellProviderInterface_WPQ_\", \"CellReady\", cellReadyArgs);\n"
               + "    }\n"
               + "//-->\n"
               + "</SCRIPT>"));
         }
         else //Connected server-side
         {
            //If connected then display all cell child controls
            if (_cellConnectedCount > 0)
            {
               //Just render some informational text
               output.RenderBeginTag(HtmlTextWriterTag.Br);
               output.RenderEndTag();
               output.RenderBeginTag(HtmlTextWriterTag.H5);
               output.Write("Connected Server-Side");
               output.RenderEndTag();
               output.RenderBeginTag(HtmlTextWriterTag.Br);
               output.RenderEndTag();

               //Render the TextBox control
               _cellInput.RenderControl(output);

               //Render the Button
               _cellButton.RenderControl(output);
            }
            else
            {
               //There wasn't a cell connection formed,
               //so just output a message
               output.Write("NO CELL INTERFACE CONNECTION");
            }
         }
      }

      //Step #11.1 (Supporting Methods): CreateChildControls
      protected override void CreateChildControls()
      {
         //Create the Button
         _cellButton = new Button();
         _cellButton.ID = "CellButton";
         _cellButton.Text = "Fire CellReady";
         Controls.Add(_cellButton);
      
         //Create the TextBox
         _cellInput = new TextBox();
         _cellInput.ID = "CellInput";
         Controls.Add(_cellInput);

         //Set the Cell information.
         //This information will be passed to the Consumer by
         //firing the CellProviderInit event.
         _cellName = "CellInput";
         _cellDisplayName = "CellDisplayInput";
   
         _cellClicked = false; // Initialize to false -- user hasn't clicked yet
         _cellButton.Click += new EventHandler(CellButtonClicked); // listen for Button's click event
      }

      //Step #11.2 (Supporting Methods): CellButtonClicked
      // <param name="sender">The Button object</param>
      // <param name="e">The Event Arguments</param>
      private void CellButtonClicked(object sender, EventArgs e)
      {
         _cellClicked = true; //user clicked button, set to true
      }
   }
}
'--------------------------------------------------------------------
' File : CellProvider.cs
'
' Purpose : A sample connectable Web Part that implements the 
'          ICellProvider interface.
'
'---------------------------------------------------------------------

Imports System
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.ComponentModel
Imports Microsoft.SharePoint.WebPartPages
Imports Microsoft.SharePoint.WebPartPages.Communication
Imports System.Runtime.InteropServices

Namespace ICellDemo
    ''' <summary>
    ''' The CellProvider Web Part class implementes the ICellProvider 
    ''' interface. Its UI is very basic - it displays a simple text 
    ''' box and button.  The CellConsumer Web Part class implements 
    ''' the ICellConsumer interface.  When the CellProvider is
    ''' connected to the CellConsumer on a Web Part Page, the CellProvider 
    ''' can pass the value in its text box to the CellConsumer which displays 
    ''' the value inline.
    ''' </summary>
    ''' 

    'Step #1: Implement the Connection Interface (ICellProvider)
    Public Class CellProvider
        Inherits WebPart
        Implements ICellProvider
        'Step #2: Declare Connection Events
        Public Event CellProviderInit As CellProviderInitEventHandler
        Public Event CellReady As CellReadyEventHandler

        'Used to keep track of whether or not the connection will be running client-side
        Private _runAtClient As Boolean = False

        'Keep a count of ICell connections
        Private _cellConnectedCount As Integer = 0

        'Web Part UI
        Private _cellButton As Button
        Private _cellInput As TextBox

        'Cell information
        Private _cellName As String
        Private _cellDisplayName As String

        'Used to keep track of whether or not the Button in the Web Part was clicked
        Private _cellClicked As Boolean = False


        'Step #3: EnsureInterfaces
        'Notification to the Web Part that is should ensure that all
        'its interfaces are registered using RegisterInterface.
        Public Overrides Sub EnsureInterfaces()
            'Registers an interface for the Web Part
            RegisterInterface("MyCellProviderInterface_WPQ_", InterfaceTypes.ICellProvider, WebPart.UnlimitedConnections, ConnectionRunAt.ServerAndClient, Me, "CellProviderInterface_WPQ_", "Provide String from Textbox", "Provides a Textbox string") 'Description - MenuLabel - InterfaceClientReference - InterfaceObject - RunAtOptions - MaxConnections - InterfaceType - InterfaceName
        End Sub


        'Step #4: CanRunAt - called by framework to determine where a part can run.
        Public Overrides Function CanRunAt() As ConnectionRunAt
            'This Web Part can run on both the client and the server
            Return ConnectionRunAt.ServerAndClient
        End Function

        'Step #5: PartCommunicationConnect - Notification to the Web Part that it has been connected.
        Public Overrides Sub PartCommunicationConnect(ByVal interfaceName As String, ByVal connectedPart As WebPart, ByVal connectedInterfaceName As String, ByVal runAt As ConnectionRunAt)
            'Check to see if this is a client-side part
            If runAt Is ConnectionRunAt.Client Then
                'This is a client-side part
                _runAtClient = True
                Return
            End If

            'Must be a server-side part so need to create the Web Part's controls
            EnsureChildControls()

            'Check if this is my particular cell interface
            If interfaceName = "MyCellProviderInterface_WPQ_" Then
                'Keep a count of the connections
                _cellConnectedCount += 1
            End If
        End Sub

        'Step #6: PartCommunicationInit - Notification to the Web Part that it has been connected.
        Public Overrides Sub PartCommunicationInit()
            'If the connection wasn't actually formed then don't want to send Init event
            If _cellConnectedCount > 0 Then
                'If there is a listener, send Init event
                If CellProviderInitEvent IsNot Nothing Then
                    'Need to create the args for the CellProviderInit event
                    Dim cellProviderInitArgs As New CellProviderInitEventArgs()

                    'Set the FieldName
                    cellProviderInitArgs.FieldName = _cellName
                    cellProviderInitArgs.FieldDisplayName = _cellDisplayName

                    'Fire the CellProviderInit event.
                    RaiseEvent CellProviderInit(Me, cellProviderInitArgs)
                End If
            End If
        End Sub

        'Step #7: PartCommunicationMain - Called by the framework to allow part to fire any remaining events
        Public Overrides Sub PartCommunicationMain()
            'If the connection wasn't actually formed then don't want to send Ready event
            If _cellConnectedCount > 0 Then
                'If there is a listener, send CellReady event
                If CellReadyEvent IsNot Nothing Then
                    'Need to create the args for the CellProviderInit event
                    Dim cellReadyArgs As New CellReadyEventArgs()

                    'If user clicked button then send the value
                    If _cellClicked Then
                        'Set the Cell to the value of the TextBox text
                        'This is the value that will be sent to the Consumer
                        cellReadyArgs.Cell = _cellInput.Text
                    Else
                        'The user didn't actually click the button
                        'so just send an empty string to the Consumer
                        cellReadyArgs.Cell = ""
                    End If


                    'Fire the CellReady event.
                    'The Consumer will then receive the Cell value
                    RaiseEvent CellReady(Me, cellReadyArgs)
                End If
            End If
        End Sub

        'Step #8: GetInitArgs is not needed in this case. GetInitEventArgs only needs to be
        'implemented for interfaces that can participate in a transformer which are 
        'the following: ICellConsumer, IRowProvider, IFilterConsumer, IParametersOutProvider, 
        'IParametersInConsumer

        'Step #9: Implement CellConsumerInit event handler.
        Public Sub CellConsumerInit(ByVal sender As Object, ByVal cellConsumerInitArgs As CellConsumerInitEventArgs)
            'This is where the Provider part could see what type of "Cell" the Consumer
            'was expecting/requesting.
            'For this simple code example, this information is not used anywhere.
        End Sub

        'Step #10: RenderWebPart - defines Web Part UI and behavior
        Protected Overrides Sub RenderWebPart(ByVal output As HtmlTextWriter)
            'Need to ensure that all of the Web Part's controls are created
            EnsureChildControls()

            'Render client connection code if the connection is client-side
            If _runAtClient Then
                'Connected client-side
                output.Write(ReplaceTokens("<br><h5>Connected Client-Side</h5><br>" & vbLf & "<input type=""text"" id=""CellInput_WPQ_""/>" & vbLf & "<button id=""CellButton_WPQ_"" onclick=""CellButtonOnClick_WPQ_()"">Fire CellReady</button>" & vbLf & "<SCRIPT LANGUAGE=""JavaScript"">" & vbLf & "<!-- " & vbLf & "    var CellProviderInterface_WPQ_ = new myCellProviderInterface_WPQ_();" & vbLf & "    function myCellProviderInterface_WPQ_()" & vbLf & "    {" & vbLf & "        this.PartCommunicationInit = myInit;" & vbLf & "        this.PartCommunicationMain = myMain;" & vbLf & "        this.CellConsumerInit = myCellConsumerInit;" & vbLf & "        function myInit()" & vbLf & "        {" & vbLf & "            var cellProviderInitArgs = new Object();" & vbLf & "            cellProviderInitArgs.FieldName = ""CellName"";" & vbLf & "            WPSC.RaiseConnectionEvent(""MyCellProviderInterface_WPQ_"", ""CellProviderInit"", cellProviderInitArgs);" & vbLf & "        }" & vbLf & "        function myMain()" & vbLf & "        {" & vbLf & "            var cellReadyArgs = new Object();" & vbLf & "            cellReadyArgs.Cell = """";" & vbLf & "            WPSC.RaiseConnectionEvent(""MyCellProviderInterface_WPQ_"", ""CellReady"", cellReadyArgs);" & vbLf & "        }" & vbLf & "        function myCellConsumerInit(sender, cellConsumerInitArgs)" & vbLf & "        {" & vbLf & "        }" & vbLf & "    }" & vbLf & "    function CellButtonOnClick_WPQ_()" & vbLf & "    {" & vbLf & "        var cellReadyArgs = new Object();" & vbLf & "        cellReadyArgs.Cell = document.all(""CellInput_WPQ_"").value;" & vbLf & "        WPSC.RaiseConnectionEvent(""MyCellProviderInterface_WPQ_"", ""CellReady"", cellReadyArgs);" & vbLf & "    }" & vbLf & "//-->" & vbLf & "</SCRIPT>"))
            Else 'Connected server-side
                'If connected then display all cell child controls
                If _cellConnectedCount > 0 Then
                    'Just render some informational text
                    output.RenderBeginTag(HtmlTextWriterTag.Br)
                    output.RenderEndTag()
                    output.RenderBeginTag(HtmlTextWriterTag.H5)
                    output.Write("Connected Server-Side")
                    output.RenderEndTag()
                    output.RenderBeginTag(HtmlTextWriterTag.Br)
                    output.RenderEndTag()

                    'Render the TextBox control
                    _cellInput.RenderControl(output)

                    'Render the Button
                    _cellButton.RenderControl(output)
                Else
                    'There wasn't a cell connection formed,
                    'so just output a message
                    output.Write("NO CELL INTERFACE CONNECTION")
                End If
            End If
        End Sub

        'Step #11.1 (Supporting Methods): CreateChildControls
        Protected Overrides Sub CreateChildControls()
            'Create the Button
            _cellButton = New Button()
            _cellButton.ID = "CellButton"
            _cellButton.Text = "Fire CellReady"
            Controls.Add(_cellButton)

            'Create the TextBox
            _cellInput = New TextBox()
            _cellInput.ID = "CellInput"
            Controls.Add(_cellInput)

            'Set the Cell information.
            'This information will be passed to the Consumer by
            'firing the CellProviderInit event.
            _cellName = "CellInput"
            _cellDisplayName = "CellDisplayInput"

            _cellClicked = False ' Initialize to false -- user hasn't clicked yet
            AddHandler _cellButton.Click, AddressOf CellButtonClicked ' listen for Button's click event
        End Sub

        'Step #11.2 (Supporting Methods): CellButtonClicked
        ' <param name="sender">The Button object</param>
        ' <param name="e">The Event Arguments</param>
        Private Sub CellButtonClicked(ByVal sender As Object, ByVal e As EventArgs)
            _cellClicked = True 'user clicked button, set to true
        End Sub
    End Class
End Namespace
//--------------------------------------------------------------------
// File : CellConsumer.cs
//
// Purpose : A sample connectable Web Part that implements the 
//          ICellConsumer interface.
//
//---------------------------------------------------------------------
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.WebPartPages.Communication;
using System.Runtime.InteropServices;

namespace ICellDemo
{

   //Step #1: Implement the Connection Interface (ICellConsumer)
   public class CellConsumer : WebPart, ICellConsumer
   {
      
      //Step #2: Declare Connection events
      public event CellConsumerInitEventHandler CellConsumerInit;

      //Used to keep track of whether or not the connection will be running client-side
      private bool _runAtClient = false;

      //Keep a count of ICell connections
      private int _cellConnectedCount = 0;

      //Web Part UI
      private Label _cellLabel;

      //Cell information
      private string _cellName;
      private string _cellDisplayName;

      //Step #3: EnsureInterfaces
      //Notification to the Web Part that is should ensure that all
      //its interfaces are registered using RegisterInterface.
      public override void EnsureInterfaces()
      {
         //Registers an interface for the Web Part.
         RegisterInterface("MyCellConsumerInterface_WPQ_",   //InterfaceName
            InterfaceTypes.ICellConsumer,               //InterfaceType
            WebPart.UnlimitedConnections,               //MaxConnections
            ConnectionRunAt.ServerAndClient,            //RunAtOptions
            this,                                 //InterfaceObject
            "CellConsumerInterface_WPQ_",               //InterfaceClientReference
            "Get String Value",                        //MenuLabel
            "Just a simple ICellConsumer");               //Description
      }

      //Step #4: CanRunAt - called by framework to determine where a part can run.
      public override ConnectionRunAt CanRunAt()
      {
         //This Web Part can run on both the client and the server
         return ConnectionRunAt.ServerAndClient;
      }

      //Step #5: PartCommunicationConnect - Notification to the Web Part that it has been connected.
      public override void PartCommunicationConnect(string interfaceName,
         WebPart connectedPart,
         string connectedInterfaceName,
         ConnectionRunAt runAt)
      {
         //Check to see if this is a client-side part
         if (runAt == ConnectionRunAt.Client)
         {
            //This is a client-side part
            _runAtClient = true;
            return;
         }
         
         //Must be a server-side part so need to create the Web Part's controls
         EnsureChildControls(); 

         //Check if this is my particular cell interface
         if (interfaceName == "MyCellConsumerInterface_WPQ_")
         {
            //Keep a count of the connections
            _cellConnectedCount++;
         }
      }

      //Step #6: PartCommunicationInit - Notification to the Web Part that it has been connected.
      public override void PartCommunicationInit()
      {
         //If the connection wasn't actually formed then don't want to send Init event
         if(_cellConnectedCount > 0)
         {
            //If there is a listener, send init event
            if (CellConsumerInit != null)
            {
               //Need to create the args for the CellConsumerInit event
               CellConsumerInitEventArgs cellConsumerInitArgs = new CellConsumerInitEventArgs();
               
               //Set the FieldNames
               cellConsumerInitArgs.FieldName = _cellName;

               //Fire the CellConsumerInit event.
               //This basically tells the Provider Web Part what type of
               //cell the Consuemr is expecting in the CellReady event.
               CellConsumerInit(this, cellConsumerInitArgs);
            }
         }
      }

      //Step #7: PartCommunicationMain - this method doesn't need to be implemented for the Consumer
      //because the Consumer doesn't have any events that need to be fired during this phase.


      //Step #8: GetInitArgs - called by the connection authoring tool, e.g., browser or SharePoint Designer
      //to get the data required to build the transformer UI.
      public override InitEventArgs GetInitEventArgs(string interfaceName)
      {
         //Check if this is my particular cell interface
         if (interfaceName == "MyCellConsumerInterface_WPQ_")
         {
            EnsureChildControls();

            //Need to create the args for the CellConsumerInit event
            CellConsumerInitEventArgs cellConsumerInitArgs = new CellConsumerInitEventArgs();
               
            //Set the FieldName
            cellConsumerInitArgs.FieldName = _cellName;
            cellConsumerInitArgs.FieldDisplayName = _cellDisplayName;
               
            //return the InitArgs
            return(cellConsumerInitArgs);
         }
         else
         {
            return(null);
         }
      }

      
   
      //Step #9.1: Implement CellProviderInit Event Handler.
      public void CellProviderInit(object sender, CellProviderInitEventArgs cellProviderInitArgs)
      {
         //This is where the Consumer part could see what type of "Cell" the Provider
         //will be sending.
         //For this simple code example, this information is not used anywhere.
      }

      //Step #9.2: Implement CellReady Event Handler. 
      //Set label text based on value from the CellProvider Web Part
      public void CellReady(object sender, CellReadyEventArgs cellReadyArgs)
      {
         //Set the label text to the value of the "Cell" that was passed by the Provider
         if(cellReadyArgs.Cell != null)
         {
            _cellLabel.Text = cellReadyArgs.Cell.ToString();
         }
      }

      //Step #10: RenderWebPart - defines Web Part UI and behavior
      protected override void RenderWebPart(HtmlTextWriter output)
      {
         //Need to ensure that all of the Web Part's controls are created
         EnsureChildControls();

         //Render client connection code if needed
         if (_runAtClient)
         {
            //Connected client-side
            string strClientCode = "<br><h5>Connected Client-Side</h5><br>\n";
            strClientCode += "<div id=\"ConsumerDiv_WPQ_\"/>\n";
            strClientCode += "<SCRIPT LANGUAGE=\"JavaScript\">\n";
            strClientCode += "<!-- \n";
            strClientCode += "    var CellConsumerInterface_WPQ_ = new myCellConsumerInterface_WPQ_();\n";

            strClientCode += "    function myCellConsumerInterface_WPQ_()\n";
            strClientCode += "    {\n";
            strClientCode += "        this.PartCommunicationInit = myInit;\n";
            strClientCode += "        this.CellProviderInit = myCellProviderInit;\n";
            strClientCode += "        this.CellReady = myCellReady;\n";

            strClientCode += "        function myInit()\n";
            strClientCode += "        {\n";
            strClientCode += "            var cellConsumerInitArgs = new Object();\n";
            strClientCode += "            cellConsumerInitArgs.FieldName = \"CellName\";\n";

            strClientCode += "            WPSC.RaiseConnectionEvent(\"MyCellConsumerInterface_WPQ_\", \"CellConsumerInit\", cellConsumerInitArgs);\n";
            strClientCode += "        }\n";

            strClientCode += "        function myCellProviderInit(sender, cellProviderInitArgs)\n";
            strClientCode += "        {\n";
            strClientCode += "        }\n";

            strClientCode += "        function myCellReady(sender, cellReadyArgs)\n";
            strClientCode += "        {\n";
            strClientCode += "            document.all('ConsumerDiv_WPQ_').innerHTML = cellReadyArgs.Cell;\n";
            strClientCode += "        }\n";

            strClientCode += "    }\n";
            strClientCode += "//-->\n";
            strClientCode += "</SCRIPT>";

            output.Write(ReplaceTokens(strClientCode));
         }
         else //Connected server-side
         {
            //If we are connected then display all child controls
            if (_cellConnectedCount > 0)
            {         
               //Just render some informational text
               output.RenderBeginTag(HtmlTextWriterTag.Br);
               output.RenderEndTag();
               output.RenderBeginTag(HtmlTextWriterTag.H5);
               output.Write("Connected Server-Side");
               output.RenderEndTag();
               output.RenderBeginTag(HtmlTextWriterTag.Br);
               output.RenderEndTag();

               //Render the Label control
               _cellLabel.RenderControl(output);
            }
            else
            {
               //else display no connection message
               output.Write("NO CELL INTERFACE CONNECTION");
            }
         }         
      }

      //Step #11.1 (Supporting Methods): CreateChildControls
      protected override void CreateChildControls()
      {
         //Create the Label
         _cellLabel = new Label();
         _cellLabel.ID = "CellLabel";
         Controls.Add(_cellLabel);

         //Set the Cell information.
         //This information will be passed to the Provider by
         //firing the CellConsumerInit event.
         _cellName = "CellInputabc";
         _cellDisplayName = "My CellInput";
      }
   }
}
'--------------------------------------------------------------------
' File : CellConsumer.cs
'
' Purpose : A sample connectable Web Part that implements the 
'          ICellConsumer interface.
'
'---------------------------------------------------------------------
Imports System
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.ComponentModel
Imports Microsoft.SharePoint.WebPartPages
Imports Microsoft.SharePoint.WebPartPages.Communication
Imports System.Runtime.InteropServices

Namespace ICellDemo

    'Step #1: Implement the Connection Interface (ICellConsumer)
    Public Class CellConsumer
        Inherits WebPart
        Implements ICellConsumer

        'Step #2: Declare Connection events
        Public Event CellConsumerInit As CellConsumerInitEventHandler

        'Used to keep track of whether or not the connection will be running client-side
        Private _runAtClient As Boolean = False

        'Keep a count of ICell connections
        Private _cellConnectedCount As Integer = 0

        'Web Part UI
        Private _cellLabel As Label

        'Cell information
        Private _cellName As String
        Private _cellDisplayName As String

        'Step #3: EnsureInterfaces
        'Notification to the Web Part that is should ensure that all
        'its interfaces are registered using RegisterInterface.
        Public Overrides Sub EnsureInterfaces()
            'Registers an interface for the Web Part.
            RegisterInterface("MyCellConsumerInterface_WPQ_", InterfaceTypes.ICellConsumer, WebPart.UnlimitedConnections, ConnectionRunAt.ServerAndClient, Me, "CellConsumerInterface_WPQ_", "Get String Value", "Just a simple ICellConsumer") 'Description - MenuLabel - InterfaceClientReference - InterfaceObject - RunAtOptions - MaxConnections - InterfaceType - InterfaceName
        End Sub

        'Step #4: CanRunAt - called by framework to determine where a part can run.
        Public Overrides Function CanRunAt() As ConnectionRunAt
            'This Web Part can run on both the client and the server
            Return ConnectionRunAt.ServerAndClient
        End Function

        'Step #5: PartCommunicationConnect - Notification to the Web Part that it has been connected.
        Public Overrides Sub PartCommunicationConnect(ByVal interfaceName As String, ByVal connectedPart As WebPart, ByVal connectedInterfaceName As String, ByVal runAt As ConnectionRunAt)
            'Check to see if this is a client-side part
            If runAt Is ConnectionRunAt.Client Then
                'This is a client-side part
                _runAtClient = True
                Return
            End If

            'Must be a server-side part so need to create the Web Part's controls
            EnsureChildControls()

            'Check if this is my particular cell interface
            If interfaceName = "MyCellConsumerInterface_WPQ_" Then
                'Keep a count of the connections
                _cellConnectedCount += 1
            End If
        End Sub

        'Step #6: PartCommunicationInit - Notification to the Web Part that it has been connected.
        Public Overrides Sub PartCommunicationInit()
            'If the connection wasn't actually formed then don't want to send Init event
            If _cellConnectedCount > 0 Then
                'If there is a listener, send init event
                If CellConsumerInitEvent IsNot Nothing Then
                    'Need to create the args for the CellConsumerInit event
                    Dim cellConsumerInitArgs As New CellConsumerInitEventArgs()

                    'Set the FieldNames
                    cellConsumerInitArgs.FieldName = _cellName

                    'Fire the CellConsumerInit event.
                    'This basically tells the Provider Web Part what type of
                    'cell the Consuemr is expecting in the CellReady event.
                    RaiseEvent CellConsumerInit(Me, cellConsumerInitArgs)
                End If
            End If
        End Sub

        'Step #7: PartCommunicationMain - this method doesn't need to be implemented for the Consumer
        'because the Consumer doesn't have any events that need to be fired during this phase.


        'Step #8: GetInitArgs - called by the connection authoring tool, e.g., browser or SharePoint Designer
        'to get the data required to build the transformer UI.
        Public Overrides Function GetInitEventArgs(ByVal interfaceName As String) As InitEventArgs
            'Check if this is my particular cell interface
            If interfaceName = "MyCellConsumerInterface_WPQ_" Then
                EnsureChildControls()

                'Need to create the args for the CellConsumerInit event
                Dim cellConsumerInitArgs As New CellConsumerInitEventArgs()

                'Set the FieldName
                cellConsumerInitArgs.FieldName = _cellName
                cellConsumerInitArgs.FieldDisplayName = _cellDisplayName

                'return the InitArgs
                Return (cellConsumerInitArgs)
            Else
                Return (Nothing)
            End If
        End Function



        'Step #9.1: Implement CellProviderInit Event Handler.
        Public Sub CellProviderInit(ByVal sender As Object, ByVal cellProviderInitArgs As CellProviderInitEventArgs)
            'This is where the Consumer part could see what type of "Cell" the Provider
            'will be sending.
            'For this simple code example, this information is not used anywhere.
        End Sub

        'Step #9.2: Implement CellReady Event Handler. 
        'Set label text based on value from the CellProvider Web Part
        Public Sub CellReady(ByVal sender As Object, ByVal cellReadyArgs As CellReadyEventArgs)
            'Set the label text to the value of the "Cell" that was passed by the Provider
            If cellReadyArgs.Cell IsNot Nothing Then
                _cellLabel.Text = cellReadyArgs.Cell.ToString()
            End If
        End Sub

        'Step #10: RenderWebPart - defines Web Part UI and behavior
        Protected Overrides Sub RenderWebPart(ByVal output As HtmlTextWriter)
            'Need to ensure that all of the Web Part's controls are created
            EnsureChildControls()

            'Render client connection code if needed
            If _runAtClient Then
                'Connected client-side
                Dim strClientCode As String = "<br><h5>Connected Client-Side</h5><br>" & vbLf
                strClientCode &= "<div id=""ConsumerDiv_WPQ_""/>" & vbLf
                strClientCode &= "<SCRIPT LANGUAGE=""JavaScript"">" & vbLf
                strClientCode &= "<!-- " & vbLf
                strClientCode &= "    var CellConsumerInterface_WPQ_ = new myCellConsumerInterface_WPQ_();" & vbLf

                strClientCode &= "    function myCellConsumerInterface_WPQ_()" & vbLf
                strClientCode &= "    {" & vbLf
                strClientCode &= "        this.PartCommunicationInit = myInit;" & vbLf
                strClientCode &= "        this.CellProviderInit = myCellProviderInit;" & vbLf
                strClientCode &= "        this.CellReady = myCellReady;" & vbLf

                strClientCode &= "        function myInit()" & vbLf
                strClientCode &= "        {" & vbLf
                strClientCode &= "            var cellConsumerInitArgs = new Object();" & vbLf
                strClientCode &= "            cellConsumerInitArgs.FieldName = ""CellName"";" & vbLf

                strClientCode &= "            WPSC.RaiseConnectionEvent(""MyCellConsumerInterface_WPQ_"", ""CellConsumerInit"", cellConsumerInitArgs);" & vbLf
                strClientCode &= "        }" & vbLf

                strClientCode &= "        function myCellProviderInit(sender, cellProviderInitArgs)" & vbLf
                strClientCode &= "        {" & vbLf
                strClientCode &= "        }" & vbLf

                strClientCode &= "        function myCellReady(sender, cellReadyArgs)" & vbLf
                strClientCode &= "        {" & vbLf
                strClientCode &= "            document.all('ConsumerDiv_WPQ_').innerHTML = cellReadyArgs.Cell;" & vbLf
                strClientCode &= "        }" & vbLf

                strClientCode &= "    }" & vbLf
                strClientCode &= "//-->" & vbLf
                strClientCode &= "</SCRIPT>"

                output.Write(ReplaceTokens(strClientCode))
            Else 'Connected server-side
                'If we are connected then display all child controls
                If _cellConnectedCount > 0 Then
                    'Just render some informational text
                    output.RenderBeginTag(HtmlTextWriterTag.Br)
                    output.RenderEndTag()
                    output.RenderBeginTag(HtmlTextWriterTag.H5)
                    output.Write("Connected Server-Side")
                    output.RenderEndTag()
                    output.RenderBeginTag(HtmlTextWriterTag.Br)
                    output.RenderEndTag()

                    'Render the Label control
                    _cellLabel.RenderControl(output)
                Else
                    'else display no connection message
                    output.Write("NO CELL INTERFACE CONNECTION")
                End If
            End If
        End Sub

        'Step #11.1 (Supporting Methods): CreateChildControls
        Protected Overrides Sub CreateChildControls()
            'Create the Label
            _cellLabel = New Label()
            _cellLabel.ID = "CellLabel"
            Controls.Add(_cellLabel)

            'Set the Cell information.
            'This information will be passed to the Provider by
            'firing the CellConsumerInit event.
            _cellName = "CellInputabc"
            _cellDisplayName = "My CellInput"
        End Sub
    End Class
End Namespace

请参阅

其他资源

ASP.NET Web 部件连接概述