Exemplarische Vorgehensweise: Erstellen von verbindbaren Webparts in SharePoint Foundation
Letzte Änderung: Donnerstag, 29. September 2011
Gilt für: SharePoint Foundation 2010
Inhalt dieses Artikels
Informationen zu verbindbaren Webparts
Erstellen eines Webparts, das die ICellProvider-Schnittstelle implementiert
Schritt 1: Erstellen der Schnittstellenklasse
Schritt 2: Deklarieren von Ereignissen
Schritt 3: Überschreiben der EnsureInterfaces-Methode und anschließendes Aufrufen der RegisterInterface-Methode
Schritt 4: Überschreiben der CanRunAt-Methode
Schritt 5: Überschreiben der PartCommunicationConnect-Methode
Schritt 6: Überschreiben der PartCommunicationInit-Methode
Schritt 7: Überschreiben der PartCommunicationMain-Methode
Schritt 8: Überschreiben der GetInitEventArgs-Methode
Schritt 9: Implementieren der Schnittstellenereignishandler
Schritt 10: Überschreiben der RenderWebPart-Methode
Schritt 11: Implementieren von unterstützenden Methoden
Ein Paar Beispielwebparts, die die Schnittstellen "ICellProvider" und "ICellConsumer" implementieren
In dieser Programmieraufgabe wird das Erstellen von zwei verbindbaren SharePoint-Webparts gezeigt: einem Webpart, das einen einzelnen Zellenwert verwenden kann, und einem weiteren Webpart, das einen einzelnen Zellenwert bereitstellen kann.
![]() |
---|
Die Webpartinfrastruktur in Microsoft SharePoint Foundation wurde über der Microsoft ASP.NET-Webpartinfrastruktur erstellt, und Webparts, die von der ASP.NETWebPart-Klasse abgeleitet sind, werden in SharePoint vollständig unterstützt. Dies schließt das ASP.NET-Verbindungsmodell ein. Wenn möglich sollten Sie ASP.NET-Webparts erstellen und das ASP.NET-Verbindungsmodell zum Verbinden der Webparts verwenden. Weitere Informationen zum Auswählen der besten WebPart-Basisklasse für die Ableitung finden Sie unter Developing Web Parts in Windows SharePoint Services. Weitere Informationen zu ASP.NET-Webparts und dem Verbindungsmodell finden Sie unter Übersicht über Webpartsverbindungen in der ASP.NET-Dokumentation. |
Informationen zu verbindbaren Webparts
Die SharePoint-Webpartinfrastruktur stellt eine standardisierte Gruppe von Schnittstellen zur Verfügung, die als Verbindungsschnittstellen bezeichnet werden. Mithilfe dieser Schnittstellen können Webparts zur Laufzeit Informationen untereinander austauschen. Das in SharePoint Foundation integrierte Listenwebpart kann eine Zeile für ein beliebiges anderes Webpart bereitstellen (an dieses senden), das diese Reihe verwenden (empfangen) kann, z. B. ein Webpart, das ein Formular zum Anzeigen der Zeile implementiert.
Da die Webpartinfrastruktur eine Standardgruppe von Verbindungsschnittstellen bereitstellt, können verbindbare Webparts von den verschiedensten Entwicklern oder Unternehmen entwickelt werden, die miteinander kommunizieren. Ein Webpart, das Verbindungsschnittstellen unterstützt, kann von einem Endbenutzer mit einem Server mit Microsoft SharePoint Designer oder einem Webbrowser verbunden werden. Dadurch können Endbenutzer komplexe Kombinationen von Webparts über eine einfache menügesteuerte Benutzeroberfläche erstellen.
Die SharePoint Foundation-Verbindungsklassen und -Schnittstellen sind im Microsoft.SharePoint.WebPartPages.Communication-Namespace implementiert.
Verbindungsschnittstellen
Verbindungsschnittstellen sind gepaarte Ereignisse, die für ein spezifisches Element, wie eine Zeile in einer Liste, relevant sind. Die gepaarten Schnittstellen bilden einen Kommunikationsbus zwischen Webparts, die diesen implementieren. Ein verbindbares Webpart ruft ein Schnittstellenereignis für mindestens ein verbundenes Webpart auf, um eine gemeinsame Aktion auszuführen. Schnittstellen sind als Anbieter für einen Consumer gepaart. Ereignisse des Anbieters werden vom Consumer behandelt und umgekehrt. In der folgenden Tabelle wird jedes Paar von Verbindungsschnittstellen kurz beschrieben.
Paar von Verbindungsschnittstellen |
Beschreibung |
---|---|
Verbindungsschnittstellen zum Bereitstellen und Verwenden eines Element mit einem einzelnen Wert, z. B. einer Zelle oder eines Felds. |
|
Verbindungsschnittstellen zum Bereitstellen und Verwenden einer einzelnen Zeile (oder mehrerer Zeilen) von Werten. |
|
Verbindungsschnittstellen zum Bereitstellen und Verwenden einer ganzen Liste. |
|
Verbindungsschnittstellen zum Bereitstellen und Verwenden eines Filterwerts. Das SharePoint-Listenwebpart unterstützt beispielsweise IListProvider, IRowProvider und IFilterConsumer. Da IRowProvider eine Verbindung mit IFilterConsumer herstellen kann, können zwei verschiedene SharePoint-Listen miteinander verbunden werden. Dadurch kann eine Liste die andere verbundene Liste filtern. |
|
Die IParameterIn-Schnittstellen ermöglichen das Übergeben und Empfangen einer beliebigen Gruppe von zufälligen Parametern zwischen Webparts. Diese Schnittstellen werden in einer Situation verwendet, in der das Consumerwebpart die Parameterliste besitzt und dies anderen Webparts mitteilen muss. |
|
Die IParameterOut-Schnittstellen ermöglichen das Übergeben und Empfangen einer beliebigen Gruppe von zufälligen Parametern zwischen Webparts. Diese Schnittstellen werden in einer Situation verwendet, in der das Anbieterwebpart die Parameterliste besitzt und dies anderen Webparts mitteilen muss. |
Kompatibilitätsregeln
Webparts können nur verbunden werden, wenn sie kompatibel sind. Es folgen mehrere Kompatibilitätsregeln, die von der Webpartinfrastruktur bei der Ermittlung bewertet werden, ob zwei Webparts verbunden werden können. Falls die Webparts nicht kompatibel sind, wird das Menüelement Verbindung im Browser deaktiviert, und eine QuickInfo erläutert den Grund für die Inkompatibilität.
Gegenpaare
Eine Verbindungsschnittstelle kann nur mit anderen kompatiblen Schnittstellen verbunden werden. Die grundlegendste Kompatibilitätsregel besagt, dass Schnittstellen als Gegenpaare oder über einen Transformator verbunden werden müssen. Eine Verbindung als Gegenpaar bedeutet, dass ein Webpart, das die IRowProvider-Schnittstelle implementiert, mit einem anderen Webpart verbunden werden kann, das die IRowConsumer-Schnittstelle implementiert.
Transformatoren
Wenn ein Webpart eine Verbindung mit einem anderen Webpart herstellen muss, das nicht genau dieselbe Schnittstelle verwendet, werden von der Webpartinfrastruktur Schnittstellentransformatoren bereitgestellt, mit denen Benutzer zwei besondere Schnittstellen in einer natürlichen und transparenten Art und Weise verbinden können.
Ein Benutzer möchte beispielweise eine Kontaktliste mit einem Bildviewer verbinden. Die Kontaktliste verwendet jedoch nur die IRowProvider-Schnittstelle und der Bildviewer nur die ICellConsumer-Schnittstelle. Zur Lösung dieses Problems wird ein Schnittstellentransformator bereitgestellt, der es diesen beiden Schnittstellen erlaubt, eine Verbindung herzustellen.
Die folgende Tabelle zeigt die Schnittstellenpaare, die über einen Transformator miteinander verbunden werden können, und es wird angegeben, ob die Verbindungen Microsoft SharePoint Designer 2010 erfordern.
Transformator |
Verbinden im Browser |
Verbinden in SharePoint Designer 2010 |
---|---|---|
Ja |
Ja |
|
Ja |
Ja |
|
Nein |
Ja |
|
Nein |
Ja |
Seitenübergreifende Verbindungen
Einige Schnittstellen können eine Verbindung mit Webparts auf einer anderen Seite herstellen. Das Verhalten ist ähnlich wie bei einem Hyperlink.
Sie sollten Folgendes zu seitenübergreifenden Verbindungen wissen:
Ein mit SharePoint Foundation kompatibler Webseiten-Editor, wie SharePoint Designer 2010, ist zum Erstellen von seitenübergreifenden Verbindungen erforderlich. Wenn eine seitenübergreifende Verbindung erstellt wurde, kann sie zur Laufzeit von jedem unterstützten Webbrowser verwendet werden.
Nur verbindbare Webparts mit Implementierungen zur Ausführung auf dem Server (die CanRunAt-Methode hat den ConnectionRunAt-Wert Server oder ServerAndClient) können seitenübergreifende Verbindungen herstellen. Die auf der Clientseite erstellten Verbindungen dürfen nicht seitenübergreifend verwendet werden.
In der folgenden Tabelle sind Schnittstellen dargestellt, die seitenübergreifend verbunden werden können.
Schnittstelle der Quellseite |
Schnittstelle der Zielseite |
---|---|
Bei Verwendung von seitenübergreifenden Webpartverbindungen müssen Sie folgende Aktionen ausführen:
Übergeben von ConnectionRunAt.Server oder ConnectionRunAt.ServerAndClient an den runAtOptions-Parameter der RegisterInterface-Methode.
Übergeben von true an den allowCrossPageConnection-Parameter der RegisterInterface-Methode.
Implementieren der GetInitEventArgs-Methode zum Bereitstellen spezifischer Informationen zu Daten, die über die Verbindungsschnittstelle übergeben werden.
Client- und Serververbindungen
Webparts können jederzeit auf dem Client oder Server ausgeführt werden. Einige Webparts können, falls sie entsprechend entworfen sind, die Bedingungen erkennen, unter denen sie ausgeführt werden, und dynamisch wechseln, um auf dem Client oder dem Server ausgeführt zu werden. Webparts können nur mit anderen Webparts verbunden werden, die an demselben Speicherort ausgeführt werden. Die serverseitigen Webparts können beispielsweise nur mit anderen serverseitigen Webparts ausgeführt werden. Serverseitige Webparts können nicht mit clientseitigen Webparts verbunden werden. Die Verbindungskette muss homogen sein. Falls ein Webpart dynamisch zwischen Client- oder Serververbindungen wechseln kann, wird die Webpartinfrastruktur das Webpart automatisch als clientseitiges oder serverseitiges Webpart festlegen, je nachdem, in welcher Webpartkette die Verbindung hergestellt ist.
Maximale Anzahl von Verbindungen
Beim Registrieren einer Schnittstelle kann die maximale Anzahl von Verbindungen zu anderen Webparts im maxConnections-Parameter der RegisterInterface-Methode angegeben werden. Falls die maximale Anzahl von Verbindungen in einem Webpart überschritten wird, kann dieses nicht mehr mit weiteren Webparts verbunden werden.
Die Optionen lauten 1 oder Unbegrenzt.
WebPart.UnlimitedConnections gibt an, dass ein verbindbares Webpart eine unbegrenzte Anzahl von Verbindungen zu einem anderen Webpart akzeptieren kann.
WebPart.LimitOneConnection gibt an, dass ein verbindbares Webpart nur eine Verbindung akzeptieren kann.
Keine zirkulären Verbindungen
Ein Webpart darf keine Verbindung zu sich selbst herstellen, weder direkt noch über eine Kette von Verbindungen.
Freigegebene und private Webpartverbindungen
Ein freigegebenes Webpart kann mit einem privaten Webpart verbunden werden, wenn das private Webpart ein Consumer ist und das freigegebene Webpart eine unbegrenzte Anzahl von Verbindungen unterstützt.
Programmfluss
Verbundene Webparts übergeben untereinander Informationen durch das Auslösen spezifischer Schnittellenereignisse. Wenn ein Webpart eine Schnittstelle wie ICellProvider implementiert, müssen zahlreiche Methoden überschrieben werden. Das Auslösen von Schnittstellenereignissen wird von der Webpartinfrastruktur ausgeführt, indem zu bestimmten Zeiten in die überschriebenen Methoden aufgerufen wird. In den folgenden Schritten zum Erstellen von verbindbaren Webparts wird definiert, welche Methoden überschrieben werden müssen, und es wird gezeigt, welchen typischen Code ein Webpartautor hierzu verwenden sollte.
Erstellen eines Webparts, das die ICellProvider-Schnittstelle implementiert
In dieser Programmieraufgabe wird der Prozess des Erstellens einer Klasse definiert, die alle erforderlichen Methoden und Ereignisse für eine Verbindungsschnittstelle mithilfe der ICellProvider-Schnittstelle implementiert. Ein vollständiges Codebeispiel finden Sie in den Quellcodebeispielen ICellProvider und ICellConsumer am Ende dieser Schritte.
Es folgen die 11 Schritte auf oberster Ebene, die Sie zum Implementieren einer Verbindungsschnittstelle für das Webpart abschließen müssen:
Erstellen der Schnittstellenklasse.
Deklarieren von Ereignissen.
Überschreiben der EnsureInterfaces-Methode und anschließendes Aufrufen der RegisterInterface-Methode.
Überschreiben von CanRunAt.
Überschreiben von PartCommunicationConnect.
Überschreiben von PartCommunicationInit.
Überschreiben von PartCommunicationMain.
Überschreiben von GetInitEventArgs.
Implementieren der Schnittstellenereignishandler.
Überschreiben von RenderWebPart.
Implementieren von unterstützenden Methoden.
Schritt 1: Erstellen der Schnittstellenklasse
Erstellen Sie eine Klasse, die eine der vordefinierten Verbindungsschnittstellen implementiert. In diesem Beispiel wird die ICellProvider-Schnittstelle implementiert. Für die verbleibenden Schritte (2-11) ist der gesamte Code in dieser Klasse vorhanden.
Beispiel
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
Schritt 2: Deklarieren von Ereignissen
Deklarieren Sie alle relevanten Ereignisse für die Verbindungsschnittstelle. Andere Variablen, die vom Webpart verwendet werden, werden ebenfalls an diesem Speicherort deklariert. Da die ICellProvider-Schnittstelle verwendet wird, werden im folgenden Beispiel Variablen für die Ereignisse CellProviderInit und CellReady deklariert.
Beispiel
// 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
Schritt 3: Überschreiben der EnsureInterfaces-Methode und anschließendes Aufrufen der RegisterInterface-Methode
Überschreiben Sie die EnsureInterfaces-Methode. Diese Methode wird von der Webpartinfrastruktur aufgerufen, bevor das Webpart gerendert wird, und zu diesem Zeitpunkt sollten alle Schnittstellen des Webparts durch Aufrufen einer der beiden RegisterInterface-Methoden registriert werden.
Beispiel
public override void EnsureInterfaces()
{
// Register Interfaces (See following section)
}
Public Overrides Sub EnsureInterfaces()
' Register Interfaces (See following section)
End Sub
Innerhalb der überschriebenen EnsureInterfaces-Methode wird die Webpartinfrastruktur über die verwendeten Schnittstellen informiert, indem die RegisterInterface-Methode aufgerufen wird. Wie in Schritt 3 vermerkt tritt die RegisterInterface-Methode innerhalb der EnsureInterfaces-Methode auf. Die RegisterInterface-Methode enthält mehrere Parameter, die unten definiert sind.
Methodendefinition
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
![]() |
---|
Es ist eine zweite RegisterInterface-Methode verfügbar, die einen zusätzlichen allowCrossPageConnection-Parameter verwendet, um explizit anzugeben, ob eine Schnittstelle seitenübergreifende Verbindungen unterstützt. Die RegisterInterface-Methode, die diesen Parameter nicht enthält, hartcodiert die Einstellung des allowCrossPageConnection-Parameters für alle Verbindungsschnittstellen, die von den durch die Webpartinfrastruktur definierten Verbindungskompatibilitätsregeln unterstützt werden (siehe "Seitenübergreifende Verbindungen" weiter oben in diesem Thema) auf true. Alle anderen Verbindungsschnittstellen werden auf false hartcodiert. |
Methodenparameter
Parameter |
Beschreibung |
---|---|
interfaceName |
Eine Zeichenfolgeneigenschaft mit dem angezeigten Namen der Schnittstelle. Der angezeigte Namen sollte in einem Webpart eindeutig sein. Diese Eigenschaft darf die folgenden Sonderzeichen nicht enthalten: <, >, &, doppelte Anführungszeichen, einfache Anführungszeichen, Komma oder Semikolon. |
interfaceType |
Eine Eigenschaft zur Darstellung des Schnittstellentyps (IRowProvider, ICellConsumer usw.). |
maxConnections |
Eine Eigenschaft, die von der Webpartinfrastruktur abgefragt werden kann, um zu bestimmen, wie viele Verbindungen für eine bestimmte Schnittstelle erstellt werden können. maxConnections ist ein int-Element. Es kann den Wert WebPart.LimitOneConnection oder WebPart.UnlimitedConnections besitzen. |
runAtOptions |
Definiert, ob die Schnittstelle ausgeführt werden kann (Client, Server, ClientAndServer, None). |
interfaceObject |
Ein Verweis auf das tatsächliche Objekt, das diese Schnittstelle implementiert. |
interfaceClientReference |
Für clientseitige Verbindungen ist interfaceClientReference eine Zeichenfolge, die als Bezeichner für das clientseitige Objekt verwendet wird, das diese Schnittstelle implementiert. Diese ID sollte ein _WPQ_-Token enthalten, um die Eindeutigkeit des Namens zu garantieren. Sie kann Sonderzeichen wie () enthalten. Es kann eine leere Zeichenfolge verwendet werden, wenn das Webpart die clientseitige Kommunikation nicht unterstützt. Die Webpartinfrastruktur codiert doppelte Anführungszeichen als einzelne Anführungszeichen. ![]()
WPQ_ ist ein Token, das von der Webpartinfrastruktur durch eine eindeutige ID ersetzt wird, wenn ein Webpart gerendert wird.
|
menuLabel |
Eine allgemeine Bezeichnung oder Erklärung der Schnittstelle. Sie wird in der Benutzeroberfläche des Verbindungsmenüs angezeigt. Es wird empfohlen, dass die Menübezeichnung mit einem Verb wie "Bereitstellen" oder "Verwenden" beginnt, sodass der eine Verbindung erstellende Benutzer die Richtung des Datenflusses versteht. |
description |
Eine erweiterte Beschreibung der Schnittstelle. |
Beispiel
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
![]() |
---|
Schließen Sie zum Erfassen von Ausnahmen zur Berechtigung für die Codezugriffssicherheit den RegisterInterface-Aufruf in einen try/catch-Block ein. Ein Beispiel hierzu finden Sie im Thema zur RegisterInterface-Methode. |
Schritt 4: Überschreiben der CanRunAt-Methode
Alle verbindbaren Webparts müssen die CanRunAt-Methode überschreiben. Diese Methode wird von der Webpartinfrastruktur aufgerufen, um zu bestimmen, ob ein Webpart auf dem Server, dem Client oder auf beiden ausgeführt werden kann. Das Webpart muss basierend auf der aktuellen Konfiguration des Benutzerclients und den anderen Webparts, mit denen es verbunden ist, bestimmen, wo es ausgeführt werden kann. Bei den zurückgegebenen Werten kann es sich um die folgenden ConnectionRunAt-Enumerationswerte handeln: Client, Server, ClientAndServer und None. Ein Webpart kann beispielsweise zwei verschiedene Renderingformate aufweisen: erweitert und reduziert. Möglicherweise muss für das Webpart eine ActiveX-Komponente für sein erweitertes Rendering installiert sein. In diesem Fall würde die CanRunAt-Methode Client zurückgeben, falls die ActiveX-Komponente installiert ist, oder Server, falls dies nicht der Fall ist.
Beispiel
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;
}
Schritt 5: Überschreiben der PartCommunicationConnect-Methode
Alle verbindbaren Webparts müssen die PartCommunicationConnect-Methode überschreiben. Diese Methode wird von der Webpartinfrastruktur aufgerufen, um das Webpart darüber zu informieren, dass es verbunden wurde, und um relevante Informationen weiterzugeben, beispielsweise mit welchem Webpart es verbunden wurde. Dies geschieht, sobald die Webpartinfrastruktur die entsprechenden Ereignisse für die Verbindung verknüpft. In dieser Methode sollte der Webpartautor nachverfolgen, wo die Schnittstelle ausgeführt werden kann, er sollte die erforderlichen Steuerelemente für die Benutzeroberflächen erstellen und überprüfen, ob die Verbindung ordnungsgemäß hergestellt wurde. Diese Methode enthält mehrere Parameter, die unten definiert sind.
Methodendefinition
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
Methodenparameter
Parameter |
Beschreibung |
---|---|
interfaceName |
Angezeigter Name der Schnittstelle, die verbunden wird. |
connectedPart |
Verweis auf das andere Webpart, mit dem eine Verbindung hergestellt wird. Sowohl der connectedPart- als auch der connectedInterfaceName-Parameter stellen eine Möglichkeit für das verbindende Webpart bereit, den Typ von Webpart zu identifizieren, mit dem eine Verbindung hergestellt wird. Dies ermöglicht, dass das Webpart eine besser informierte Interaktion mit dem anderen Webpart durchführt. Wenn das Quellwebpart ausführliche Details zum Zielwebpart besitzt, kann das Quellwebpart das Objektmodell des Zielwebparts verwenden. Beide Webparts müssen jedoch für diesen Zweck entworfen worden sein, damit dies ordnungsgemäß funktioniert. Ein Diagrammwebpart und ein Pivotwebpart könnten beispielsweise so entworfen werden, dass sie dasselbe Layout einer gemeinsamen Datenquelle verwenden, wenn sie miteinander verbunden werden. |
connectedInterfaceName |
Angezeigter Name der Schnittstelle in dem anderen Webpart, über das sie verbunden sind. |
runAt |
Ort, an dem die Schnittstelle ausgeführt werden kann. Dies ist entweder der Client oder der Server. Bestimmt wird dies von der Webpartinfrastruktur auf der Grundlage mehrerer Faktoren. |
Beispiel
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
Schritt 6: Überschreiben der PartCommunicationInit-Methode
Ein verbindbares Webpart kann optional die PartCommunicationInit-Methode überschreiben. Diese Methode wird von der Webpartinfrastruktur aufgerufen, damit das Webpart Initialisierungsereignisse auslösen kann. Das Webpart sollte Ereignisse mit der Endung "Init" auslösen (z. B. CellProviderInit).
Init-Parameter sind hilfreich, wenn ein Webpart Informationen zu sich selbst an andere Webparts übertragen muss. Wenn ein Listenwebpart z. B. eine Verbindung mit einem Formularwebpart herstellt, kann das Listenwebpart seine Feldnamen übertragen. Das Formularwebpart könnte dann seine Benutzeroberfläche basierend auf den Feldnamen aus dem Listenwebpart rendern.
Beispiel
![]() |
---|
Für clientseitige Webparts müssen dieses Ereignis und sein Ereignishandler auf dem Client implementiert sein. |
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
Schritt 7: Überschreiben der PartCommunicationMain-Methode
Ein verbindbares Webpart kann optional die PartCommunicationMain-Methode überschreiben. Sie wird von der Webpartinfrastruktur aufgerufen, damit das Webpart andere Ereignisse aus der Schnittstelle auslösen kann (z. B. CellReady). Während der Ausführung der PartCommunicationMain-Methode findet die tatsächliche Kommunikation der Datenwerte (im Gegensatz zum Schema) zwischen den Webparts statt.
Beispiel
![]() |
---|
Für clientseitige Webparts müssen dieses Ereignis und sein Ereignishandler auf dem Client implementiert sein. |
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
Schritt 8: Überschreiben der GetInitEventArgs-Methode
Ein verbindbares Webpart sollte die GetInitEventArgs-Methode bei Bedarf überschreiben. Die GetInitEventArgs-Methode ist nur für Schnittstellen erforderlich, die Transformatoren verwenden. Beispielsweise können IRowProvider, ICellConsumer, IFilterConsumer, IParametersOutProvider und IParametersInConsumer Transformatoren unterstützen. Die GetInitEventArgs-Methode wird von den Verbindungserstellungstools für alle Anfangsdaten verwendet, die zum Erstellen der Transformaturbenutzeroberfläche erforderlich sind. Die Methode gibt das InitEventArgs-Objekt zurück und fügt den Schnittstellennamen ein.
Wenn beispielsweise zwei Webparts verbunden werden, die die Schnittstellen IRowProvider und ICellConsumer unterstützen, muss der Benutzer angeben, welches Feld im IRowProvider-Webpart dem Eingabewert in dem ICellConsumer-Webpart zugeordnet wird. Dazu ruft die Webpartinfrastruktur die GetInitEventArgs-Methode in jeder Schnittstelle auf. Die Verbindungserstellungstools wie SharePoint Designer oder der Browser verwenden die übergebenen Init-Parameter zum Erstellen der Benutzeroberfläche für den Transformator, in der der Benutzer die Feldzuordnung auswählen kann.
Methodendefinition
public override InitEventArgs GetInitEventArgs(string interfaceName)
Public Overrides Function GetInitEventArgs(ByVal interfaceName As String) As InitEventArgs
End Function
Methodenparameter
Parameter |
Beschreibung |
---|---|
interfaceName |
Eine Zeichenfolgeneigenschaft mit dem angezeigten Namen der Schnittstelle. |
Beispiel
![]() |
---|
Diese Methode kann auf dem Server oder dem Client implementiert werden. |
![]() |
---|
Ein Codebeispiel für ein Webpart, das die ICellProvider-Schnittstelle implementiert, wurde als Beispiel in diesen Schritten verwendet. Die ICellProvider-Schnittstelle sollte jedoch die GetInitEventArgs-Methode nicht überschreiben, da sie keinen Transformator verwenden kann. Aus Gründen der Vollständigkeit folgt nun jedoch ein Beispiel aus dem Codebeispiel CellConsumer.cs am Ende dieser Programmieraufgabe, in dem die GetInitEventArgs-Methode überschrieben wird. |
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
Schritt 9: Implementieren der Schnittstellenereignishandler
Implementieren Sie die entsprechenden Ereignishandler basierend auf dem Typ der verwendeten Schnittstelle. In diesem Beispiel muss die ICellProvider-Schnittstelle den CellConsumerInitEventHandler-Ereignishandler implementieren. Dieser Ereignishandler muss unabhängig davon implementiert werden, ob die durch die ICellConsumer-Schnittstelle übergebenen Daten verwendet werden oder nicht. Das Consumerwebpart löst dieses Ereignis aus, wenn seine PartCommunicationInit-Methode ausgeführt wird.
Methodendefintion
public void CellConsumerInit(object sender, CellConsumerInitEventArgs cellConsumerInitEventArgs)
Methodenparameter
Parameter |
Beschreibung |
---|---|
sender |
Das diese Methode aufrufende Objekt. |
cellConsumerInitEventArgs |
Parameter, die vom Consumerwebpart während der PartCommunicationInit-Phase übergeben werden. |
Beispiel
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
Schritt 10: Überschreiben der RenderWebPart-Methode
Alle Webparts müssen die RenderWebPart-Methode überschreiben. Die Details hierzu sind für jedes Webpart spezifisch. Die Webpartinfrastruktur ruft diese Methode zum Rendern des Webparts auf. Ein vollständiges Beispiel finden Sie im Quellcode CellProvider.cs am Ende dieses Themas mit Programmieraufgabe. Es folgt ein kurzes Codeskelett als Beispiel.
Beispiel
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
Schritt 11: Implementieren von unterstützenden Methoden
An dieser Stelle im Quellcode ICellProvider sollten alle unterstützenden Methoden definiert werden. Ein Codeskelett ist unten aufgeführt. Ein vollständiges Beispiel finden Sie im Quellcode CellProvider.cs am Ende dieses Themas mit Programmieraufgabe.
Beispiel
// 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
Ein Paar Beispielwebparts, die die Schnittstellen "ICellProvider" und "ICellConsumer" implementieren
Die folgenden beiden Codebeispiele zeigen das Erstellen von zwei verbindbaren Webparts, die die Schnittstellen ICellProvider und ICellConsumer implementieren.
Wenn Sie diese Programmieraufgabe abschließen möchten, können Sie die folgenden Codebeispiele ausschneiden und in zwei C#-Dateien Ihres Webpartprojekts einfügen und dann das Projekt erstellen.
//--------------------------------------------------------------------
// 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