Tutorial Creating Custom Web Parts

Download as pdf or txt
Download as pdf or txt
You are on page 1of 34

Creating Custom Web Parts

How to Contact Us
Worldwide Offices
Email: [email protected]
OSIsoft Australia
Web: http://vCampus.osisoft.com > Contact Us
Perth, Australia
Auckland, New Zealand
OSIsoft Europe
OSIsoft, LLC. Altenstadt, Germany
777 Davis St., Suite 250 OSI Software Asia Pte Ltd.
San Leandro, CA 94577 USA Singapore
OSIsoft Canada ULC
Houston, TX
Montreal, Quebec
Johnson City, TN
Calgary, Alberta
Mayfield Heights, OH
Phoenix, AZ OSIsoft, Inc. Representative Office
Savannah, GA Shanghai, People’s Republic of China
Seattle, WA OSIsoft Japan KK
Yardley, PA Tokyo, Japan
OSIsoft Mexico S. De R.L. De C.V.
Mexico City, Mexico

Sales Outlets and Distributors


 Brazil  South America/Caribbean
 Middle East/North Africa  Southeast Asia
 Republic of South Africa  South Korea
 Russia/Central Asia  Taiwan

WWW.OSISOFT.COM

OSIsoft, LLC. is the owner of the following trademarks and registered trademarks: PI System, PI
ProcessBook, Sequencia, Sigmafine, gRecipe, sRecipe, and RLINK. MATLAB® is a registered
trademark of The MathWorks, Inc. All terms mentioned in this book that are known to be trademarks or
service marks have been appropriately capitalized. Any trademark that appears in this book that is not
owned by OSIsoft, Inc. is the property of its owner and use herein in no way indicates an endorsement,
recommendation, or warranty of such party’s products or any affiliation with such party of any kind.

RESTRICTED RIGHTS LEGEND


Use, duplication, or disclosure by the Government is subject to restrictions as set forth in subparagraph
(c)(1)(ii) of the Rights in Technical Data and Computer Software clause at DFARS 252.227-7013

Unpublished – rights reserved under the copyright laws of the United States.

© 1998-2011 OSIsoft, LLC


Table of Contents
OVERVIEW ....................................................................................................................................................... 4

ABOUT THIS DOCUMENT ...................................................................................................................... 4

WHAT YOU NEED TO START .................................................................................................................... 4

CREATING A CUSTOM WEB PART THAT SUPPORTS CLIENT-SIDE CONNECTIONS ...................................... 5

CREATING A BASE WEB PART ................................................................................................................ 6

TESTING THE WEB PART .......................................................................................................................... 9

MAKING THE WEB PART CONNECTABLE ......................................................................................... 15

TESTING THE CONNECTABLE WEB PART .......................................................................................... 20

ADDING A PROPERTY AND MAKING THE WEB PART WEB-EDITABLE ........................................ 24

TESTING THE WEB PART'S WEB-EDITABLE PROPERTY ................................................................. 28

ADDING CLIENT-SIDE CONNECTIVITY ................................................................................................. 29

TESTING CLIENT-SIDE CONNECTIVITY ................................................................................................ 34

REVISION HISTORY......................................................................................................................................... 34
OVERVIEW

ABOUT THIS DOCUMENT


This document is exclusive to the OSIsoft Virtual Campus (vCampus) and is available on its online
Library, located at http://vCampus.osisoft.com/Library/library.aspx. As such, it is provided 'as is'
and is not supported by OSIsoft's regular Technical Support.

Any question or comment related to this document should be posted in the appropriate OSIsoft
vCampus discussion forum (http://vCampus.osisoft.com/forums) or sent to the OSIsoft vCampus
Team at [email protected].

WHAT YOU NEED TO START


You must have the following software installed to complete this exercise:

 PI Server 3.3 or higher


 Microsoft Visual Studio 2010
 Microsoft Windows Server 2008
 SharePoint Foundation 2010 or SharePoint Server 2010
 PI WebParts 2010 R2

4
CREATING A CUSTOM WEB PART THAT SUPPORTS
CLIENT-SIDE CONNECTIONS
A web part page is made up of zones, and each zone may contain web parts which can interact with one
another, by sending data from part to part using web part connection technology. SharePoint supports
both server-side and client-side connections. With a server-side connection, data from the providing part is
sent to the SharePoint server, which results in a re-rendering of the web part page so that the data sent
can be represented in the receiving part; in other words, the browser refreshes. With a client-side
connection, data is transmitted from the providing part directly to the consuming part, without the
browser refreshing.

OSIsoft provides a range of web parts that allow you to do a great deal of things with time-series data, but
at times there are specific needs that cannot be addressed with OSIsoft’s parts. This tutorial
demonstrates how to create your own web part that can connect to ours with either a server-side
connection or a client-side connection.

5
CREATING A BASE WEB PART
You’ll be using Microsoft Visual Studio 2010.

1. Create a new project in Visual Studio 2010. Be sure to start Visual Studio 2010 with Administrative
privileges; if you don’t you may be prompted to restart it later. To start Visual Studio 2010 with
Administrative privileges, right click the Visual Studio 2010 icon and select “Run as administrator”
from the popup menu.

2. Under Visual C#, locate SharePoint, then click 2010, and select Visual Web Part. Name it
“WebPartConnectionsTutorial” and click OK.

6
3. Validate the SharePoint site that you will use for debugging, and then click Finish to Deploy as a
farm solution.

7
At this point you should get a default web part created, and you can open VisualWebPart1.cs.

4. In VisualWebPart1.cs, change the class from which your web part derives, from
System.Web.UI.WebControls.WebParts.WebPart to
Microsoft.SharePoint.WebPartsPages.WebPart (this older class is necessary for support of client-
side connections between web parts).

//Change it from this...


public class VisualWebPart1 : WebPart

//to this
public class VisualWebPart1 : Microsoft.SharePoint.WebPartPages.WebPart

5. To check your progress, add the 'Hello World' code below to the CreateChildControls function and
compile and deploy your project (Deploy Solution from the Build menu in Visual Studio).

//Replace the contents of CreateChildControls with this code


Label label = new Label();
label.Text = "Hello World";
Controls.Add(label);

8
TESTING THE WEB PART
6. Go to your SharePoint site, pull down the Site Actions menu, and select More Options…

9
7. On the Create page, choose to filter by Page, then select Web Part Page and click the Create
button.

10
8. Give a name to the page (e.g. WebPartConnections.aspx), select the Header, Footer, 3 Columns
layout, and then click Create.

11
9. Click the Add a Web Part link in the Left Column of the new web part page, select your part from
the Custom category, and click the Add button.

12
You should see the “Hello World” text appear in your web part in Edit mode.

13
10. Click the Stop Editing button in the Ribbon to see your web part in run mode.

14
MAKING THE WEB PART CONNECTABLE
11. Back in VisualWebPart1.cs, change the class declaration to implement an additional interface:
IParametersOutProvider. In addition, add a using directive to import the
Microsoft.SharePoint.WebPartPages.Communication namespace.

//Add this “using” directive near the top of the source file
using Microsoft.SharePoint.WebPartPages.Communication;

//Change the class definition from this...


public class VisualWebPart1 : Microsoft.SharePoint.WebPartPages.WebPart

//to this
public class VisualWebPart1 : Microsoft.SharePoint.WebPartPages.WebPart, IParametersOutProvider

12. Declare the events that this web part will handle.

//Add these event declarations to the class


public event NoParametersOutEventHandler NoParametersOut;
public event ParametersOutProviderInitEventHandler ParametersOutProviderInit;
public event ParametersOutReadyEventHandler ParametersOutReady;

15
At this point the source file for your class should look something like this:

16
13. Override the EnsureInterfaces method with a call to the RegisterInterface method to register the
IParametersOutProvider interface that you want to expose to other web parts.

//Add this to your web part class


[Obsolete]
public override void EnsureInterfaces()
{
RegisterInterface("TagListProvider_WPQ_", InterfaceTypes.IParametersOutProvider, UnlimitedConnections,
CanRunAt(), this, "TagListProvider_WPQ_", "Provide list item", "Provides list item to connected part");
}

14. Override the ConnectionRunAt method; for now, we’ll only run on the server side.

//Add this to your web part class


[Obsolete]
public override ConnectionRunAt CanRunAt()
{
return ConnectionRunAt.Server;
}

15. Override the PartCommunicationConnect method, to keep track of whether or not there is a
connection, and whether it is server-side or client-side.

//Add this to your web part class


private bool paramsOutConnected = false;
private bool paramsOutRunAtServer = false;
[Obsolete]
public override void PartCommunicationConnect(string interfaceName, Microsoft.SharePoint.WebPartPages.WebPart
connectedPart, string connectedInterfaceName, ConnectionRunAt runAt)
{
paramsOutConnected = true;
paramsOutRunAtServer = (runAt == ConnectionRunAt.Server);
}

16. Override the PartCommunicationInit method, so that when requested, your custom part will
respond that it has one value to share via connection, “TagName”.

//Add this to your web part class


[Obsolete]
public override void PartCommunicationInit()
{
ParametersOutProviderInitEventArgs args = new ParametersOutProviderInitEventArgs();
args.ParameterOutProperties = new ParameterOutProperty[1];
args.ParameterOutProperties[0] = new ParameterOutProperty();
args.ParameterOutProperties[0].ParameterName = "TagName";
args.ParameterOutProperties[0].ParameterDisplayName = "Selected Tag";
args.ParameterOutProperties[0].Description = "The selected tag name";
ParametersOutProviderInit(this, args);
}

17
17. Override the PartCommunicationMain method, to send the selected tag name when requested.

private DropDownList dropDownList;


[Obsolete]
public override void PartCommunicationMain()
{
EnsureChildControls();
ParametersOutReadyEventArgs args = new ParametersOutReadyEventArgs();
args.ParameterValues = new string[1];
args.ParameterValues[0] = dropDownList.SelectedValue;
ParametersOutReady(this, args);
}

18. Override the RenderWebPart method. The JavaScript part of this override is the standard way to
make an ASP.NET “post back”, and is only enabled for the “onchange” JavaScript event. The
parameters to that function are the UniqueID of the element that raised the event, and the event
arguments.

protected override void RenderWebPart(HtmlTextWriter output)


{
EnsureChildControls();
if (paramsOutConnected && paramsOutRunAtServer)
{
dropDownList.Attributes["onchange"] = "javascript:__doPostBack('" + this.UniqueID + "', '');";
}
base.RenderWebPart(output);
}

18
19. Now re-implement the CreateChildControls method, replacing the original “Hello World” content,
to draw the drop-down list inside an HTML table. Also add a using directive for
System.Web.UI.HtmlControls.

//Add this...
using System.Web.UI.HtmlControls;

//Change the CreateChildControls implementation from this...


protected override void CreateChildControls()
{
Label label = new Label();
label.Text = "Hello World";
Controls.Add(label);
}

//to this...
string textData = "Sinusoid\r\nCDT158\r\nSinusoidU";
protected override void CreateChildControls()
{
base.CreateChildControls();

HtmlTable htmlTable = new HtmlTable();


HtmlTableRow tr = new HtmlTableRow();
htmlTable.Rows.Add(tr);
HtmlTableCell tc = new HtmlTableCell();
tr.Cells.Add(tc);
Label titleLabel = new Label();
titleLabel.Font.Bold = true;
titleLabel.Text = "Value";
tc.Controls.Add(titleLabel);
tr.Cells.Add(new HtmlTableCell());

dropDownList = new DropDownList();


tc.Controls.Add(dropDownList);
Controls.Add(htmlTable);
}

20. Override the base class’ OnPreRender method in VisualWebPart1.cs to fill the drop-down list with
the tag choices.

//Add this code to the class


protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);

dropDownList.Items.Clear();
string[] arrText = textData.Split(new string[1] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < arrText.Length; i++)
{
dropDownList.Items.Add(new ListItem((string)arrText[i], (string)arrText[i]));
}
}

19
TESTING THE CONNECTABLE WEB PART
In order to confirm this is working, build and deploy the solution and go back to the web page to see if the
changes you’ve made so far are displaying correctly - if you can see the dropdown list and its content, then
you are on the right track.

21. To see if you can connect this web part to another web part, add a PI Trend web part to your web
part page. Click on the Page tab in the SharePoint ribbon, and then click the Edit Page button in the
ribbon. Next click on the Add a Web Part link in the Footer zone, select the PI Trend web part from
the PI WebParts category, and click the Add button.

22. Pull down the web part menu for the PI Trend web part, hover over Connections to get the menu to
cascade, hover over Get client-side parameters from..., and finally click on the VisualWebPart1.

23. Now that it is connected, you’ll need to select where/how you want to use the parameter
that comes from your web part, so select Edit Web Part from the PI Trend web part menu.

20
24. Look for the Selected Data section in the PI Trend toolpane and click on the Connections lightning
bolt button.

21
25. You'll be presented with another window that lists all of the web parts that are connected to the PI
Trend. Click on VisualWebPart1 and then Selected Tag, and then click the OK button.

22
26. Click the OK button in the PI Trend toolpane, then verify that the connection is working – the first
tag in the drop-down list in your web part is “Sinusoid”, and that should be selected, and traced in the
PI Trend. Selecting another tag in the dropdown list on your custom web part will update the trend
with the selected tag. Note that even if you leave Edit mode, the connection between these two
web parts will still take place server-side – the entire web part page will refresh when you choose a
different tag in the drop-down list.

23
ADDING A PROPERTY AND MAKING THE WEB PART WEB-EDITABLE
Since you would not want your web part to always present the same list of tags, it would be nice to let the
end-user specify the tags that should appear in the list. To provide a mechanism in the web part toolpane that
allows the user to specify the list of tags, you need to make this web part “web-editable”.

27. First, to simplify the code that you need to add, put a using directive in the VisualWebPart1.cs file
for Microsoft.SharePoint.WebPartPages. Next, extend you class definition to inherit from a third
interface – IWebEditable – and implement the read-only WebBrowsableObject property for this
interface. Finally, change the list of tags to start as empty, and implement a TextData property that
can be edited in the toolpane.

//Add support for the IWebEditable Interface

using Microsoft.SharePoint.WebPartPages;

//Change this...
public class VisualWebPart1: Microsoft.SharePoint.WebPartPages.WebPart, IParametersOutProvider

//to this
public class VisualWebPart1: Microsoft.SharePoint.WebPartPages.WebPart, IParametersOutProvider, IWebEditable

//Implement the WebBrowsableObject property of the IWebEditable interface to indicate that this web part
//has properties that should be accessible via the SharePoint toolpane
object IWebEditable.WebBrowsableObject
{
get { return this; }
}

//Change the textData definition to start with no list of tags, and add a TextData property
private string textData = string.Empty;

[WebDisplayName("Text Data"),Category("Configuration"), WebBrowsable(false), WebPartStorage(Storage.Personal)]


public string TextData
{
get { return textData; }
set { textData = value; }
}

24
28. Right-click on the WebPartConnectionsTutorial project in the Solution Explorer pane, then hover
over Add and select Class... from the cascading menu. Add a new class to the project and call it
WebPartPropertyEditor.

29. Add the following using directives to the new WebPartPropertyEditor class to simplify the code.

//Add this to the 'using' definitions


using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

Your new WebPartPropertyEditor class should look like this:

25
30. Replace the entire class definition with the code below to make it inherit from the EditorPart class
and override some of its members:

class WebPartPropertyEditor : EditorPart


{
private TextBox textData;
public WebPartPropertyEditor()
{
ID = "WebPartPropertyEditor";
}

protected override void CreateChildControls()


{
base.CreateChildControls();
Label label = new Label();
label.Text = "Data";
Controls.Add(label);
Controls.Add(new HtmlGenericControl("br"));
textData = new TextBox();
textData.TextMode = TextBoxMode.MultiLine;
textData.Rows = 5;
textData.Wrap = false;
textData.Width = 200;
Controls.Add(textData);
Controls.Add(new HtmlGenericControl("br"));
}

public override bool ApplyChanges()


{
VisualWebPart1.VisualWebPart1 listProvider = (VisualWebPart1.VisualWebPart1)WebPartToEdit;
listProvider.TextData = textData.Text;
return true;
}

public override void SyncChanges()


{
EnsureChildControls();
VisualWebPart1.VisualWebPart1 listProvider = (VisualWebPart1.VisualWebPart1)WebPartToEdit;
textData.Text = listProvider.TextData;
}
}

26
31. Now you need to go back and implement the IWebEditable interface’s CreateEditorParts method.
This is done in the VisualWebPart1 class, in the VisualWebPart1.cs source file.

//Add this to the 'using' directives


using System.Collections.Generic;

//Add this code to the class


EditorPartCollection IWebEditable.CreateEditorParts()
{
List<EditorPart> editorPartList = new List<EditorPart>();
editorPartList.Add(new WebPartPropertyEditor());
return new EditorPartCollection(editorPartList);
}

27
TESTING THE WEB PART'S WEB-EDITABLE PROPERTY
32. Build and deploy the solution and go to the web part page created earlier; you may need to close
Internet Explorer and then re-open it to see the change in your web part. The drop-down list of tags
should now be empty. Pull down the web part menu for your web part, and select Edit Web Part. In
the toolpane, locate the empty Data list, and type in the tag names (e.g. "CDT158", "SINUSOID" and
"SINUSOIDU") in the Data list, one per line.

33. Click the OK button in the toolpane, and you should now see the tags that you typed in the
previous step available from the drop-down list. When you change the selection in the drop-down
list, the PI Trend updates to show the new tag. However, this is all still happening server-side.

28
ADDING CLIENT-SIDE CONNECTIVITY
34. Return to Visual Studio 2010. Add a new item to the WebPartConnectionsTutorial project by right-
clicking the project, hovering over the Add item to get the menu to cascade, and then clicking on
New Item…

35. In the list of Installed Templates on the left, choose the Web template under Visual C#, then select
JScript File, name it TagListProvider.js, and click the Add button.

29
36. Paste the code below into the empty TagListProvider.js file. This is the client-side connection code.

<SCRIPT LANGUAGE="JavaScript">
<!--
//TagListProvider object is the client-side implementation of the ParametersOutProvider interface
function TagListProvider(wpq, dropDownListClientID, title)
{
this.WPQ = wpq;
this.DropDownListClientID = dropDownListClientID;
this.Title = title;

this.RaiseParametersOut = _raiseParametersOut;
this.PartCommunicationInit = _partCommunicationInit;
this.PartCommunicationMain = _partCommunicationMain;
this.ParametersOutReady = _parametersOutReady;
this.NoParametersOut = _noParametersOut;

function _raiseParametersOut()
{
var a r g s = new Object();
a r g s .ParameterValues = new Array(1);
var dropDownList = document.all(this.DropDownListClientID);
var selectedValue = dropDownList.options[dropDownList.selectedIndex].value;
a r g s .ParameterValues[0] = selectedValue;
this.ParametersOutReady(a r g s );
}

function _partCommunicationInit()
{
var args = new Object();
args.ParameterOutProperties = new Array(1);
args.ParameterOutProperties[0] = new Object();
args.ParameterOutProperties[0].ParameterName = "TagName";
args.ParameterOutProperties[0].ParameterDisplayName = "Selected Tag";
args.ParameterOutProperties[0].Description = "The selected tag name";
args.ParameterOutProperties[0].Required = false;
WPSC.RaiseConnectionEvent("TagListProvider" + this.WPQ, "ParametersOutProviderInit", args);
}

function _partCommunicationMain()
{
this.RaiseParametersOut();
}

function _parametersOutReady(a r g s )
{
WPSC.RaiseConnectionEvent("TagListProvider" + this.WPQ, "ParametersOutReady", a r g s );
}

function _noParametersOut()
{
}
}
-->
</SCRIPT>

30
37. Change the Build Action for this JScript file to Embedded Resource.

38. Now that we have the client-side script that we need, return to the VisualWebPart1.cs file, and
modify the CanRunAt method to make it return ConnectionRunAt.Server if it is in
BrowserDesignMode, and return ConnectionRunAt.ServerAndClient otherwise.

//Replace the CanRunAt function in your class with this


[Obsolete]
public override ConnectionRunAt CanRunAt()
{
if (this.BrowserDesignMode) return ConnectionRunAt.Server;
return ConnectionRunAt.ServerAndClient;
}

31
39. Add the GetScript method to VisualWebpart1. This method will return the JScript file we embedded
in the project earlier, and will be invoked in the OnPreRender method (see next step).

//Add these to the 'using' directives


using System.IO;
using System.Reflection;

//Add this code to the class


private string GetScript()
{
string script = string.Empty;

Assembly thisAssembly = Assembly.GetExecutingAssembly();


Stream stream = thisAssembly.GetManifestResourceStream("WebPartConnectionsTutorial.TagListProvider.js");

using (StreamReader reader = new StreamReader(stream))


{
script = reader.ReadToEnd();
}
return script;
}

32
40. Add code to the base class’ OnPreRender method in VisualWebPart1.cs to generate client-side
connection code when appropriate.

//Change OnPreRender from this…


protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);

dropDownList.Items.Clear();
string[] arrText = textData.Split(new string[1] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < arrText.Length; i++)
{
dropDownList.Items.Add(new ListItem((string)arrText[i], (string)arrText[i]));
}
}

//to this
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);

dropDownList.Items.Clear();
string[] arrText = textData.Split(new string[1] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < arrText.Length; i++)
{
dropDownList.Items.Add(new ListItem((string)arrText[i], (string)arrText[i]));
}

if(paramsOutConnected)
{
if (!paramsOutRunAtServer)
{
dropDownList.Attributes["onchange"] =
string.Format("javascript:TagListProvider{0}.RaiseParametersOut();", ReplaceTokens("_WPQ_"));
if (!Page.ClientScript.IsClientScriptBlockRegistered("ListProvider"))
Page.ClientScript.RegisterClientScriptBlock(typeof(string), "ListProvider", GetScript());
string initScript = @"var TagListProvider_WPQ_ = new TagListProvider('_WPQ_', '{0}', '{1}');";
initScript = string.Format(ReplaceTokens(initScript), dropDownList.ClientID, this.StorageKey);
Page.ClientScript.RegisterClientScriptBlock(typeof(string), ReplaceTokens("TagListProvider_WPQ_"),
initScript, true);
}
}
}

33
TESTING CLIENT-SIDE CONNECTIVITY
At this point you should build and deploy your web point, then return to the web part page and verify
that communication between your web part and the PI Trend now occurs without a page refresh.

REVISION HISTORY

27-Jan-10 Initial version by Cristobal Escamilla

05-Feb-10 Revised version by Cristobal Escamilla, with the help of the OSIsoft vCampus Team

24-Oct-11 Updated by Paul Kaiser to use PI WebParts 2010 R2, SharePoint 2010, and Visual
Studio 2010

34

You might also like