演练:在 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 部件将引发针对一个或多个已连接的部件的接口事件,从而使其执行操作。接口是作为针对使用者的提供程序成对出现的。来自提供程序的事件由使用者处理,反之亦然。下表简要描述了每对连接接口。
连接接口对 |
说明 |
---|---|
用于提供或使用单值项目(例如一个单元格或字段)的连接接口。 |
|
用于提供或使用单行(或多行)值的连接接口。 |
|
用于提供或使用整个列表的连接接口。 |
|
用于提供或使用筛选值的连接接口。例如,SharePoint 列表 Web 部件支持 IListProvider、IRowProvider 和 IFilterConsumer。由于 IRowProvider 可以连接到 IFilterConsumer,因此可以将两个不同的 SharePoint 列表彼此连接。这样,其中的一个列表就可以筛选另一个连接的列表。 |
|
IParameterIn 接口允许传递和接收 Web 部件之间的任意参数的任何组。这些接口可用于处理使用者 Web 部件拥有参数列表并需要将其与其他 Web 部件进行通信的情况。 |
|
IParameterOut 接口允许传递和接收 Web 部件之间的任意参数的任何组。这些接口可用于处理提供程序 Web 部件拥有参数列表并需要将其与其他 Web 部件进行通信的情况。 |
兼容性规则
仅在 Web 部件兼容的情况下,才能连接这些部件。以下是几条兼容性规则,这些规则是在确定两个 Web 部件是否可以连接时由 Web 部件基础结构评定的。如果发现 Web 部件不兼容,则浏览器中的"连接"菜单项将处于禁用状态,并会出现一个工具提示,以解释不兼容的原因。
相反的对
连接接口只能与其他兼容的接口连接。最基本的兼容性规则是接口必须作为相反的对连接或通过转换器连接。作为相反的对连接意味着实现 IRowProvider 接口的 Web 部件可以与实现 IRowConsumer 接口的另一个部件连接。
转换器
在一个 Web 部件需要连接到另一个接口不完全相同的部件的情况下,Web 部件基础结构将提供接口转换器,它有助于用户通过自然而明晰的方式连接两个不同的接口。
例如,用户可能希望将联系人列表连接到图片查看器。但是,联系人列表只有 IRowProvider 接口,而图片查看器只有 ICellConsumer 接口。为了解决此问题,将提供一个可用于将这两个接口彼此连接的接口转换器。
下表显示可通过转换器彼此连接的接口对以及连接是否需要 Microsoft SharePoint Designer 2010。
转换器 |
在浏览器中 连接 |
在 SharePoint Designer 2010 中连接 |
---|---|---|
是 |
是 |
|
是 |
是 |
|
否 |
是 |
|
否 |
是 |
跨页连接
允许将一些接口连接到不同页面上的 Web 部件。此行为与超链接类似。
应了解有关跨页连接的以下信息:
与 SharePoint Foundation 兼容的网页编辑器(例如,SharePoint Designer 2010)是创建跨页连接所必需的。不过,一旦形成跨页连接,则任何受支持的 Web 浏览器均可以在运行时使用该连接。
只有具有设计为在服务器上运行的实现(CanRunAt 方法具有一个 Server 或 ServerAndClient 的 ConnectionRunAt 值)的可连接 Web 部件可建立跨页连接。不允许客户端上形成的连接跨网页。
下表演示可跨页连接的接口。
源页接口 |
目标页接口 |
---|---|
在使用跨页 Web 部件连接时,必须执行以下操作:
将 ConnectionRunAt.Server 或 ConnectionRunAt.ServerAndClient 传递给 RegisterInterface 方法的 runAtOptions 参数。
将 true 传递给 RegisterInterface 方法的 allowCrossPageConnection 参数。
实现 GetInitEventArgs 方法以提供有关通过连接接口传递的数据的特定信息。
客户端和服务器连接
在任何给定时间,都允许在客户端或服务器上运行 Web 部件。一些 Web 部件(如果根据情况进行设计)可以检测其运行条件并动态切换为在客户端或服务器上运行。只能将 Web 部件连接到在相同位置上运行的其他 Web 部件。例如,只能将服务器端部件连接到其他服务器端部件。不能将服务器端部件连接到客户端部件。连接链必须是同源的。如果某个部件可以在客户端或服务器连接之间动态切换,则 Web 部件基础结构会自动将此 Web 部件固定为客户端部件或服务器端部件,具体取决于此 Web 部件所连接到的 Web 部件链。
最大连接数
在对接口进行注册时,可以在 RegisterInterface 方法的 maxConnections 参数中指定针对其他 Web 部件的最大连接数。如果在某个 Web 部件上超出了连接限制,则不能将此部件连接到其他部件。
选项为 1 或无限制。
WebPart.UnlimitedConnections 指定可连接的 Web 部件与另一个 Web 部件的连接数不受限制。
WebPart.LimitOneConnection 指定可连接的 Web 部件只允许一个连接。
无循环连接
Web 部件不能直接或通过连接链来自我连接。
共享的和专用的 Web 部件连接
共享的 Web 部件可以连接到专用 Web 部件,如果专用 Web 部件是一个使用者且共享的 Web 部件支持无数连接。
程序流
连接的 Web 部件通过触发特定的接口事件来彼此传递信息。当 Web 部件实现接口(例如,ICellProvider)时,它必须重写大量方法。接口事件的触发操作由在指定时间调入到已重写的方法内的 Web 部件基础结构执行。以下用于创建可连接的 Web 部件的步骤定义需要重写的方法以及 Web 部件作者在执行此操作时应使用的典型代码。
创建实现 ICellProvider 接口的 Web 部件
此编程任务定义创建类的过程,该类为使用 ICellProvider 接口的连接接口实现所有必需的方法和事件。有关完整的代码示例,请参阅这些步骤结尾的 ICellProvider 和 ICellConsumer 源代码示例。
下面是 11 个高级步骤,若要实现 Web 部件的连接接口,则必须完成这些步骤:
创建接口类。
声明事件。
重写 EnsureInterfaces 方法,然后调用 RegisterInterface 方法。
重写 CanRunAt 方法。
重写 PartCommunicationConnect 方法。
重写 PartCommunicationInit 方法。
重写 PartCommunicationMain 方法。
重写 GetInitEventArgs 方法。
实现接口事件处理程序。
重写 RenderWebPart 方法。
实现支持的方法。
步骤 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 接口,因此下面的示例将声明其 CellProviderInit 和 CellReady 事件的变量。
示例
// 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 |
一个表示接口的类型(IRowProvider、ICellConsumer 等)的属性。 |
maxConnections |
一个属性,Web 部件基础结构可以查询此属性以确定可在给定接口上形成的连接的数目。maxConnections 是一个 int。它可以具有 WebPart.LimitOneConnection 或 WebPart.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 方法仅对于使用转换器的接口是必需的。例如,IRowProvider、ICellConsumer、IFilterConsumer、IParametersOutProvider 和 IParametersInConsumer 都可以支持转换器。对于创建转换器用户界面所需的所有初始数据,连接创作工具将调用 GetInitEventArgs 方法。此方法将返回 InitEventArgs 对象并接受接口名称。
例如,在连接两个支持 IRowProvider 和 ICellConsumer 接口的 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 部件
下面的两个代码示例阐释如何创建两个实现 ICellProvider 和 ICellConsumer 接口的可连接的 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