This first Sharepoint-related post is a relatively complete example of how to create a custom web part with a custom tool part that uses a pop-up modal dialog (a “Web Dialog“) to choose a value and return it to the tool part.  My sample uses a pretty silly example and only utilizes a combo box in the dialog.  However, this could easily serve as the starting point for a much more sophisticated tool part, such as one that uses a treeview or any other control that can run on a web page and return a value through DHTML. 

 

The sample is in C#, for no particular reason except that I like C#.  :)

 

 =====

 

Some Windows Sharepoint Services 2.0 or Sharepoint Portal Server 2003 customers/applications may require that a web part include a tool part that has the capability to pop up a modal dialog for the user to choose a value from. An example in the existing SPS UI would be the modal dialog that is raised when assigning an audience to a specific web part; the UI includes a link that opens a dialog that the user can choose from, and the value is returned to SPS.

 

This sample includes an additional step. The audiences example above does not return the value directly to the tool part, but uses the return value to directly set a property. This sample returns the dialog value to a HTML text box on the tool part, which can then be assigned to the associated web part by using fairly standard code behind the scenes.

 

The following steps assume the use of Web Part Templates for Visual Studio.NET, available for download from the MSDN Library online:

 

SharePoint Products and Technologies Templates: Web Part Templates for Visual Studio .NET

http://www.microsoft.com/downloads/details.aspx?FamilyId=CAC3E0D2-BEC1-494C-A74E-75936B88E3B5&displaylang=en

 

1) Create a new Web Part Library Project in VS.NET

 

Name it ToolPartOpener

 

2) Add a Web Part to the Project

 

Name it Chooser.cs

 

3) Copy-paste the entirety of the following code into Chooser.cs, replacing any and all pre-existing template code:

 

 

using System;

using System.ComponentModel;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Xml.Serialization;

using Microsoft.SharePoint;

using Microsoft.SharePoint.Utilities;

using Microsoft.SharePoint.WebPartPages;

 

namespace ToolPartOpener

{

[DefaultProperty("Text"),

ToolboxData("<{0}:Chooser runat=server></{0}:Chooser>"),

XmlRoot(Namespace="ToolPartOpener")]

public class Chooser : Microsoft.SharePoint.WebPartPages.WebPart

{

private const string defaultText = "";

 

private string text = defaultText;

 

[Browsable(false),

Category("Miscellaneous"),

DefaultValue(defaultText),

WebPartStorage(Storage.Personal),

FriendlyName("Text"),

Description("Text Property")]

public string Text

{

get

{

return text;

}

 

set

{

text = value;

}

}

 

/// <summary>

///This method gets the custom tool parts for this Web Part by overriding the

///GetToolParts method of the WebPart base class. You must implement

///custom tool parts in a separate class that derives from

///Microsoft.SharePoint.WebPartPages.ToolPart.

///</summary>

///<returns>An array of references to ToolPart objects.</returns>

 

public override ToolPart[] GetToolParts()

{

ToolPart[] toolparts = new ToolPart[3];

 

WebPartToolPart wptp = new WebPartToolPart();

CustomPropertyToolPart custom = new CustomPropertyToolPart();

 

//The following two tool parts are the default parts for a web part

toolparts[0] = wptp;

toolparts[1] = custom;

 

//A reference to the custom tool part being created

toolparts[2] = new ToolPartOpener.ChooserToolPart();

 

return toolparts;

}

 

/// <summary>

/// Render this Web Part to the output parameter specified.

/// </summary>

/// <param name="output"> The HTML writer to write out to </param>

protected override void RenderWebPart(HtmlTextWriter output)

{

output.Write("Current Value: " + SPEncode.HtmlEncode(Text));

}

}

}

 

 

4) Add a Tool Part to the Project

 

Name it ChooserToolPart.cs

 

5) Copy-paste the entirety of the following code into ChooserToolPart.cs, replacing any and all pre-existing template code:

 

 

using System;

using System.Web.UI;

using System.Web.UI.WebControls;

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebPartPages;

 

namespace ToolPartOpener

{

/// <summary>

/// Description of the toolpart. Override the GetToolParts method in your WebPart

/// class to invoke this toolpart. To establish a reference to the Web Part

/// the user has selected, use the ParentToolPane.SelectedWebPart property.

/// </summary>

public class ChooserToolPart: Microsoft.SharePoint.WebPartPages.ToolPart

{

 

private string sUniqueInputID;

private string sValue = "";

 

public ChooserToolPart()

{

//Set some properties and event handlers for the tool part

 

this.Title = "Chooser Tool Part";

this.Init += new EventHandler(InitFunc);

this.PreRender += new EventHandler(PreRenderFunc);

}

 

private void InitFunc(object sender, System.EventArgs e )

{

//Get a reference to the tool part's unique ID to use as form item identifiers

//Using a unique ID allows multiple instances per web part page

 

sUniqueInputID = "Input" + this.UniqueID;

}

 

private void PreRenderFunc(object sender , System.EventArgs e )

{

//Insert JScript on PreRender

RegisterChooserScript();

}

 

protected void RegisterChooserScript()

{

string sScriptKey = "ChooserScriptKey";

 

//The code below contatenates a string containing the JScript code

//JScript code opens a dialog window using showModalDialog() and puts

//the returnValue into a text input HTML element on the tool part page using the unique ID

 

string EmbeddedScriptFormat =

"<script language=jscript>function OpenChooserDialog(){";

EmbeddedScriptFormat +=

"var sReturnValue; ";

EmbeddedScriptFormat += "sReturnValue = window.showModalDialog";

EmbeddedScriptFormat += (\"/_layouts/ChooserDialog.htm\",\"\",\"dialogHeight:100px;";

EmbeddedScriptFormat += "dialogWidth:300px;status:no;help:no\");";

EmbeddedScriptFormat += "if(sReturnValue == undefined){;}else{";

EmbeddedScriptFormat += "window.document.all[\'" + sUniqueInputID + "\'].value = sReturnValue;}";

EmbeddedScriptFormat +=

"}</script>";

 

//Check if the script is currently registered, and register if it is not

 

if(!Page.IsClientScriptBlockRegistered(sScriptKey))

Page.RegisterClientScriptBlock(sScriptKey,

EmbeddedScriptFormat);

}

 

///<summary>

///This method is called by the ToolPane object to apply property changes to the selected Web Part.

///</summary>

 

public override void ApplyChanges()

{

ToolPartSaveProps();

}

 

private void ToolPartSaveProps()

{

//Get a reference to the web part associated with this tool part

ToolPane tpPane = this.ParentToolPane;

ToolPartOpener.Chooser wpChooser = (ToolPartOpener.Chooser)(tpPane.SelectedWebPart);

 

try

{

//Assign the returned value to the web part's Text property

sValue = Page.Request.Form[sUniqueInputID].ToString();

wpChooser.Text = sValue;

}

catch (Exception e)

{

wpChooser.Text = e.ToString();

}

 

}

 

/// <summary>

///If the ApplyChanges method succeeds, this method is called by the ToolPane object

///to refresh the specified property values in the toolpart user interface.

/// </summary>

 

public override void SyncChanges()

{

//SyncChanges() is not required in this instance; since showModalDialog() requires

//the use of client-side script, we'll be synching the values in client-side script as well

}

 

/// <summary>

///This method is called by the ToolPane object if the user discards changes to the selected Web Part.

/// </summary>

public override void CancelChanges()

{

}

 

/// <summary>

/// Render this tool part to the output parameter specified.

/// </summary>

/// <param name="output">The HTML writer to write out to </param>

protected override void RenderToolPart(HtmlTextWriter output)

{

//Get a reference to the web part associated with this tool part

ToolPane tpPane = this.ParentToolPane;

ToolPartOpener.Chooser wpChooser = (ToolPartOpener.Chooser)(tpPane.SelectedWebPart);

 

//Write the button input to the tool part page, calling client-side function which is registered in

//the RegisterChooserScript() function

 

output.Write("<br><input class='ms-SPButton' width=\"100\" value=\'Open\' type=button onclick=\"OpenChooserDialog();\" > ");

 

//Write the text input box that the client-side script targets for the return value.

//Value is set to the Text property of the associated web part

 

output.Write("<input type=\"text\" class=\"UserInput\" size=\"20\" id=\"" + sUniqueInputID + "\" name=\"" + sUniqueInputID + "\" value=\"" + wpChooser.Text.ToString() + "\">");

 

}

 

}

 

 

}

 

 

6) Add an HTML Page to the Project

 

Name it ChooserDialog.htm

 

7) Copy-paste the entirety of the following HTML and code into ChooserDialog.htm (in HTML view), replacing any and all pre-existing HTML and/or code:

 

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>

<head>

<script language=jscript>

 

function ReturnToPart()

{

window.returnValue = window.document.all["select1"].value;

window.close();

}

 

</script>

<title>Chooser Dialog</title>

</head>

<body>

<form name="form1" id="form1">

<p align="center">

<br>

<select id="select1" name="select1">

<option id="opt1" value="Elephant">Elephant</option>

<option id="opt2" value="Giraffe">Giraffe</option>

<option id="opt3" value="Zebra">Zebra</option>

</select>

<input type="Button" name="Button1" id="Button1" value="OK" onclick="jscript:ReturnToPart();">

</p>

</form>

</body>

</html>

 

 

8) Save the HTML page to an accessible, browseable location

 

Recommended deployment for the HTML page is on the server running SPS/WSS, in the LAYOUTS folder in the WSS directory structure, found in a path similar to the following.

 

x:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\LAYOUTS

 

9) Deploy the Web Part

 

Deploying Web Parts Using DWP files and Web Part Galleries

http://msdn.microsoft.com/library/en-us/spptsdk/html/smpxPkgDeployWP.asp?frame=true

 

10) Use the Tool Part and Dialog