Building the InfoPath Form Hosted on a SharePoint Site Sample Application

Testing the SharePoint Application

Conclusion

Additional Resources

Overview of Modal Dialog Boxes in SharePoint 2010

Many page activities in Microsoft SharePoint 2010 open a modal dialog box that lets you complete a task without navigating away from the current page. When the dialog box opens, the background darkens (the so-called lightbox effect), which indicates that the page is inactive. You must deal with the dialog box before you can return to the page.

Good examples are the modal dialog boxes that open when you create, view, or edit an item in a SharePoint list. Each of these dialog boxes loads a SharePoint application page (NewForm.aspx, DispForm.aspx, or EditForm.aspx) in a pop-up window. Although the pop-up window displays what is, technically speaking, a new page, the new page appears to open in the context of the page that you were on (see Figure 1). It feels like you are zooming in on the page instead of navigating away.

Figure 1. SharePoint New Item dialog box

When SharePoint 2010 creates a modal dialog box, it employs a new client-side dialog box framework that you can also use. For the most part, the functionality is encapsulated in the SP.UI.Dialog Class and SP.UI.ModalDialog Class of the JavaScript (ECMAScript) Class Library. The dialog box classes are implemented in the SP.UI.Dialog.js file, which is located in the LAYOUTS folder of your SharePoint 2010 installation. (The source code is minified for performance; if you want to browse, get the more readable companion file, SP.UI.Dialog.debug.js.)

It is not difficult to imagine situations where you might want to invoke a modal dialog box from a Microsoft InfoPath 2010 form. A classic example is a data-picker control that opens a calendar so that the person who is filling out the form can browse to and select a date. Another example is when the form requires information that is not readily available to the person who is filling it out, such as a link to an item in a SharePoint list. In this case, you might want to open a dialog box that enables the user to navigate to or search for the information that the form requires without leaving the context of the form.

In this article, you develop a sample application that demonstrates how to open a SharePoint modal dialog box from an InfoPath form. You learn how to create and test an application page and the modal dialog box that displays it. Then, you finish the application by designing a form template and creating a Web Part to host the form. When the application is complete, you deploy and test it.

Sample Application: InfoPath Form Hosted on a SharePoint Site

In the scenario for this sample, Human Resources at Contoso requested a browser-based form that each department can fill out as a first step in planning for the coming fiscal year. The form will be used to gather information about the department's current resources and forecast needs. One field in the proposed form asks for a link to a department organization chart.

To fulfill this request, you decide to design an InfoPath form that is hosted on an internal SharePoint website. As you design the form, you realize that to complete the field that asks for a link to the organization chart, the user must navigate away from the form to obtain the URL. You want to avoid any situation that causes a user to leave the form, so you decide to give the form the ability to open a modal dialog box that lets the user search for the selected file and select it.

InfoPath Form Hosted on a SharePoint Site Sample Application Architecture

The sample application has the following components:

Browser-enabled InfoPath form The title of the form is "Contoso Resource Planning." It contains a label ("Organization Chart"), a hyperlink field ("URL"), and a button ("Search"). The button click event is handled by form code that raises the NotifyHost event and passes an XPath expression for the field.

Web Part that contains an XMLFormView control The InfoPath form is hosted by an XmlFormView control inside a custom Web Part. The XMLFormView control subscribes to the NotifyHost event and handles it by invoking a modal search dialog box. When the dialog box closes, the Web Part updates the field in the form.

Modal dialog box The modal search dialog box is opened by a client script that executes in the context of the Web Parts page. The script calls a method in the SP.UI.ModalDialog Class to open a modal dialog box and display a search application page. When the modal dialog box closes, the result of the search is passed to a callback function that also executes in the context of the Web Parts page.

SharePoint application page The user interface (UI) and the logic for the search application are implemented in a SharePoint application page. For this demonstration, the application page implements a simple search among the items listed in a document library on the SharePoint website.

The relationship among the components is shown in Figure 2.

Figure 2. Sample application components and relationships

Building the InfoPath Form Hosted on a SharePoint Site Sample Application

You will develop the example application in six steps.

Step 1: Create a Search Application Page In this step, you design the UI for the page that the modal dialog box displays, and you write code to perform the search.

Step 2: Add JavaScript for the modal dialog box In this step, you create an ECMAScript (JavaScript, JScript) file with code to open the search application page in a pop-up modal dialog box. The function that opens the modal dialog box specifies a callback function that returns information about the document that the user has selected to the page that opened the dialog box.

Step 3: Test the Modal Dialog Box In this step, you do a quick test of what you have developed so far. You use the SharePoint Content Editor Web Part (CEWP) for this purpose.

Step 4: Design the InfoPath Form In this step, you create a form template that includes a Search button, and you write form code that notifies the form's host when a user clicks the button.

Step 5: Create a Web Part to Host the Form In this step, you write a custom Web Part that uses an XmlFormView control to host the InfoPath form.

Step 6: Connect the Components In this step, you put everything together. You write Web Part code that handles the NotifyHost event, code that invokes the modal dialog box, and code that uses the dialog box result to update the InfoPath form.

Application Prerequisites

You will learn more if you follow along on your own development website as you construct the sample application. To complete the application, you must have the following:

Microsoft Visual Studio 2010

InfoPath Designer 2010

Microsoft Visual Studio Tools for Applications

A server that is running Microsoft SharePoint Server 2010

You must also do some preparation on your development website. First, make sure that the root web of your SharePoint site collection has a Shared Documents library. Then populate the library with test documents that can be found by the search application. Use document names relevant to our scenario, such as "IT Department Org Chart FY11.docx," "IT Department Policies.docx," and so on.

Although not required reading, the following articles contain background information that may help explain some of the techniques that are used:

Step 1: Create a Search Application Page

Begin by creating a search application page that allows a user to search for and select a document. Our project is not about implementing search, so the application that we create simply enumerates over the Shared Documents library. You can extend it later by implementing full search.

You will build the search application page in stages. First you create the UI on the page. Then you implement the search logic in code behind the page. Finally, you deploy the application page and test it.

To create the user interface for the search application page

In Visual Studio 2010, create a new project.

In the New Project dialog box, select SharePoint 2010 and the Empty SharePoint Project template.

Name the project ModalHost. ApplicationPages, and then click OK.

In the SharePoint Customization Wizard, click Deploy as a farm solution. Then click Finish.

In Solution Explorer, right-click the project node, point to Add, then click New Item.

In the Add New Item dialog box, select the Application Page template. Name the page ModalHost.aspx, and then click Add.

In the ModalHost.aspx application page markup, locate ContentPlaceHolderID="PlaceHolderMain". Place the cursor on a blank line above the closing </asp:Content> tag. Then copy the following markup and paste it at the insertion point.

Now you must make the controls do something. Basically, you have to handle two events: the Click event raised by the ImageButton control, and the SelectedIndexChanged event raised by the SPGridView control. When the ImageButton is clicked, the handler must do the following:

Get a reference to the Shared Documents library on the current website.

Query the library for items with titles that contain the search terms.

Display the result count in the Label control.

Display the result set in the SPGridView control.

When the user selects an item in the SPGridView control, the handler for the SelectedIndexChanged event must do the following:

Extract information that you can later use to create a hyperlink from the selected document's metadata.

Store the document metadata in the DialogValue text box.

Later in this article, you will write code that passes the document metadata to a callback function that executes in the context of the search application's consumer, a Web Part.

To add code for the search application page

Click anywhere on the markup for ModalHost.aspx. Then press F7 to view the page code.

At the top of the file, add the following using statements.

using System.Web.UI;
using System.Linq;
using System.Collections.Generic;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.Utilities;

Delete contents of the ModalHost class body. Then copy the following code and paste it into the class body.

Take a moment to examine the code that you just pasted into your project.

GetDocumentLibrary This method returns the SPList object that represents the Shared Documents library and uses an output parameter to return the URL of the current SharePoint site collection.

The GetDocumentLibrary method gets a reference to the list by instantiating an SPSite object to represent the site collection, getting the SPWeb object for the root website, and then querying the list collection for the SPList object that represents the Shared Documents library. This is all fairly standard practice for programming against SharePoint data.

Notably, the code uses the site collection URL to instantiate an SPSite object, but it does not get the URL from SPContext.Current.Web.Url, as it might if it were running in the context of an ordinary content page or a Web Part. This code runs in the context of a SharePoint application page, where context information is not available. The standard practice in this case is for the consumer of the application page to pass required context information in parameters of a query string that is appended to the page URL.

The GetDocumentLibrary method gets the value of the query string parameter by calling the GetQueryStringValue method.

GetQueryStringValue This method returns the value of the url parameter in the query string that is appended to the page URL. For example, given a page URL like this:

Result This custom class contains three properties to hold document metadata (Title, URL and Created By) that are relevant here. A collection of Result objects is bound to the GridView control to display the search results.

Dosearch_Click This event handler enumerates over the items in the document library and generates a collection of Result objects that match the search criteria.

ResultGrid_SelectedIndexChanged This event handler is invoked when a user selects a row inside the gridview. It creates a semicolon-delimited string by using the selected document's title and URL. It then stores this string as the value of the Dialogvalue text box so that it can be read by the consumer application.

Now that you have a UI and code behind it, you can test the search application page.

To test the search application page

In Solution Explorer, right-click the ModalHost.ApplicationPages project node, and then click Deploy.

Type a search term in the Enter document name text box. Then click the Search button (magnifying glass).

The search results are displayed in the grid, as shown in Figure 5.

Figure 5. Search results displayed in a grid

Select a document by clicking Select in any row of the results, as shown in Figure 6.

The DialogValue text box displays a semicolon-delimited string with metadata for the selected document, as shown in Figure 6.

Figure 6. Selecting a document in the search results

Step 2: Add JavaScript for the Modal Dialog Box

The next development task is to write JavaScript to open the search application page in a pop-up modal dialog box and, when the dialog box closes, return information about the selected document to the page that opened the modal dialog box.

The example code references a particular version of the jQuery library. You can use a later version as long as you change all references in the example code to the version of the library that you are using. A simpler alternative might be to rename the file that you have downloaded to jquery-1.5.min.js.

To create the modal dialog box script

In Solution Explorer, under the Layouts folder, right-click the ModalHost.ApplicationPages folder, point to Add, and then click New Folder. Name the new folder scripts.

Right-click the scripts folder, point to Add, and then click Existing Item. Navigate to the downloaded jquery-1.5.min.js file, and then click Add.

Right-click the scripts folder, point to Add, and then click New Item. Select Visual C#, and then click General. Select the Text File template, and name the file ModalHost.js. Then click Add.

Copy the following code and paste it into ModalHost.js.

// When invoked open the modal dialog box.
// We will call this function from the Web Parts page.
function popupmodalui(url) {
// Set the required properties.
var options = { autoSize: true,
title: "Search documents",
showClose: true,
allowMaximize: true
};
// Pop up the application page in the modal dialog box,
// and pass the site URL as a query string to the application page.
SP.UI.ModalDialog.commonModalDialogOpen("../_layouts/ModalHost.ApplicationPages/ModalHost.aspx?url="
+ url,
options, closecallback, null);
}
// Handles the click event for OK button on the modal dialog box.
// This function runs in the context of the application page.
function ModalOk_click() {
// Get the value of the hidden text box on the modal dialog box.
var value = getValueByClass('.modalhiddenfield');
// Pass the hidden text box value to the callback and close the modal dialog box.
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, value);
}
// Handles the click event for the Cancel button on the modal dialog box.
function ModalCancel_click() {
// Set the dialog result property to Cancel and close the modal dialog box.
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 'Cancel clicked');
}
// Executes when the modal dialog box is closed.
// This function runs in the context of the Web Part's page.
function closecallback(result, value) {
// Determine whether the OK button was clicked.
if (result === SP.UI.DialogResult.OK) {
// Set the value of the hidden text box on the Web Part
// with the value passed by the OK button event.
var ispostback = setValue('.webparthiddenfield', value);
if (ispostback == true) {
// Postback the page so the Web Part life cycle is reinitiated.
postpage();
}
}
}
// Finds a control by CSS class name and retrieves its value.
function getValueByClass(className) {
formtextBox = $(className);
if (formtextBox != null) {
return formtextBox.val();
}
}
// Finds a control by CSS class name and sets its value.
// This function runs in the context of the Web Part's page.
function setValue(className, value) {
hiddenfieldid = $(className);
if (hiddenfieldid != null) {
hiddenfieldid.val(value);
/*For testing the modal dialog box with the CEWP. Can be removed.*/
if (hiddenfieldid.css('visibility') == "visible") {
return false;
}
/*--*/
return true;
}
}
// Check if the hidden text box on the modal dialog box is empty.
function checkTextChange() {
value = jQuery.trim(getValueByClass('.modalhiddenfield'));
// Enable the OK button on the modal window if the hidden text box has a value.
if (value) {
$('#btnModalOK').removeAttr('disabled');
}
// Disable the OK button on the modal window if the hidden text box does not have a value.
else {
$('#btnModalOK').attr("disabled", "true");
}
}
// Postback the page to reinitiate the Web Part life cycle.
function postpage() {
document.forms[0].submit();
}
// Look for a change every time the page is loaded.
$(document).ready(function () {
checkTextChange();
});

Let's review the code.

popupmodalui Opens the modal dialog box that displays the search application page. It does this by calling the SP.UI.ModalDialog.commonModalDialogOpen(url, options, callback, args) Method function and passing in the relative URL of the application page with the website URL appended in a query string parameter. As you might recall, the code behind the application page has a method to retrieve the URL from the query string.

Later in the project, you will write code that invokes the popupmodalui function from a Web Part that hosts an InfoPath form.

closecallback This function is called after the modal dialog box closes and it executes in the context of the page that called commonModalDialogOpen. If the user clicks OK to close the dialog box, the value argument is passed to the "webparthiddenfield" text box on the parent page. Later in the project, you will create this hidden text box in the Web Part that invokes the popmodalui function.

checkTextChange This function checks whether the "modalhiddenfield" text box on the application page has a value. (This is the text box whose ID is DialogValue.) If the text box does have a value, the function enables the OK button. Otherwise, it disables the button.

The search application page does not yet have a button to raise the event that this function handles.

ModalCancel_click This function closes the dialog box and passes a value that indicates that Cancel was clicked.

Note

The search application page does not yet have a button to raise the event that this function handles.

postpage This function submits the parent page, causing a partial page postback. This reinitiates the page life cycle. Later, you will write code for a Web Part that reads the value in the hidden text box in its OnPreRender event handler.

Before you continue, you should understand how the application is using hidden text boxes. The completed project will have two of them, both used for temporary storage of metadata from the document that the user selects in the modal dialog box. So far, you have created just one hidden text box, the DialogValue control on the application page. (You have not yet actually made the text box invisible. You will do that very soon.) The markup attaches the CssClass "modalhiddenfield" to the first hidden text box. This is a dummy class used to make it easier to locate the element in the page's element tree. Later in the project, you create a second hidden text box, this one on a Web Part. It will be identified by the CssClass attribute "webparthiddenfield".

When the user makes a selection in the modal dialog box, code behind the search application page stores metadata for the document in the "modalhiddenfield" text box on the application page. The click event handler for the OK button in the modal dialog box passes the value that is stored in this text box to the callback function. The callback function executes in the context of the parent page, the Web Part, and stores the value that it receives in the Web Part's "webparthiddenfield" text box. Code for the Web Part reads the "webparthiddenfield" text box and uses its value to update a hyperlink field on the InfoPath form.

Now that you have written JavaScript for the modal dialog box, you must link to the script in the markup for the application page. While you are editing the page, you can also add markup to hide the "modalhiddenfield" text box that has, until now, been visible. And you can finish by adding OK and Cancel buttons to close the dialog box.

To complete the search application page

In Visual Studio, open ModalHost.aspx.

Locate ContentPlaceHolderID="PlaceHolderAdditionalPageHead". Place the cursor on a blank line above the closing </asp:Content> tag. Then copy the following markup and paste it at the insertion point.

Step 4: Design the InfoPath Form

At this point, you have a search application page, and you can display the page in a modal dialog box. Next, you create a form to invoke the dialog box.

For the sample application, you do not require anything very complex. A very simple form will do. It must have these three elements:

A label ("Organization Chart")

A hyperlink field ("URL")

A button ("Search")

You also want to create a handler for the button click event. In the handler, you call the NotifyHost(String) method, and in the method's notification parameter, you pass an XPath expression for the field. This expression is communicated via event arguments to whatever is handling the NotifyHost event on the host. (You implement the host's side of the conversation later, in Step 6.)

Finally, finish Step 4 by publishing the form to a website that is running SharePoint Server 2010.

To design the form

In InfoPath Designer 2010, click the File tab, and then click New.

Under Available Form Templates, select Blank Form. Then click Design Form.

Click Click to add title, and then type Contoso Resource Planning.

In the body of the form, click Add tables. Click the Insert tab, and then click Custom Table. Insert a 3x1 table (three columns and one row).

Click in the first column of the table, and type Organization Chart.

Click anywhere in the second column of the table. Then click the Home tab, and in the Controls group under Objects, click Hyperlink.

A new field1 and an attribute field2 appear in the Fields task pane.

In the Fields task pane, right-click field1, and select Properties.

On the Data tab, change the Name property to URL. Click OK.

Repeat the two previous steps, this time renaming field2 to Title.

In the second column of the table, right-click the hyperlink control, and then select Hyperlink Properties. In the Hyperlink Properties dialog box (see Figure 13), select the Read-Only check box. Then click OK.

This step prevents the user from editing the hyperlink manually.

Figure 13. Hyperlink Properties dialog box

Click anywhere in the third column of the table. Then click the Home tab, and in the Controls group under Objects, click Button.

Right-click the Button control, and then select Button Properties.

In the Button Properties dialog box, change the Label property to Search, and change the ID property to InvokePopup. Then click OK.

(Optional) Customize the page layout and form style as you want.

On the File tab, click Save. Name the file ContosoResourcePlanning.xsn (see Figure 14).

Figure 14. Contoso Resource Planning form

To add a handler for the button click event

In InfoPath Designer, click the Developer tab, and then click Language.

In the Form Options dialog box, under Form template code language, select C#, and then click OK.

This is the absolute URL to the form template file. You will need this information when you configure a Web Part to host the form.

Save the text file.

Step 5: Create a Web Part to Host the Form

In the previous step, you created an InfoPath form that notifies its host whenever the Search button is clicked. Now it is time to create the host.

In this step, we create a custom Web Part that includes an XmlFormView control that can be configured to host a browser-enabled InfoPath form. In addition, the Web Part has a text box control for temporary storage of the value that is returned by the modal Search dialog box. Because the text box is used only for storage, it is styled in a way that prevents it from rendering on the page. Finally, you want the Web Part to be reusable, so you will give it a custom property that accepts the URL to a form template file.

After the Web Part is created, you redeploy the solution and add the Web Part to a page.

To create the custom Web Part

In Visual Studio, open the ModalHost.ApplicationPages solution.

In Solution Explorer, right-click the solution node, point to Add, and then click New Project. Select SharePoint, select 2010, and then select Empty Project. Name the project ModalHost.WebParts. Click OK.

The SharePoint Customization Wizard appears.

Select Deploy as a farm solution, and then click Finish.

In Solution Explorer, right-click the ModalHost.WebParts project node, point to Add, and then click New Item. Select SharePoint, select 2010, and then select Web Part. Name the Web Part InfoPathFormHost, and then click OK.

In the ModalHost.WebParts project, add a reference to Microsoft.Office.InfoPath.Server.dll by browsing to the folder <Drive Letter>:\Program Files\Microsoft Office Servers\14.0\Bin.

If Visual Studio displays a warning message, click Yes to continue adding the reference to the project.

At the top of InfoPathFormHost.css, add the following using statements:

using Microsoft.Office.InfoPath.Server.Controls;
using System.Text;

The InfoPathFormHost class contains an empty CreateChildControls method. Delete this method, and then paste the following code in the body of the InfoPathFormHost class.

This code declares the FormXSNURL property and makes it available through the Web Part's tool pane so that the user can set it with the URL of the published InfoPath form's XSN file.The code also initializes an XMLFormView control and a text box control, and adds them to the controls collection. The text box is explicitly marked as hidden on the page. It is later used to store the value that is returned by the modal dialog box.

This code overrides the OnPreRender() event handler to configure the XmlFormView control to host the InfoPath form that the Web Part's FormXSNURL property points to, and to set the control's EditingStatus property to Editing. Doing this enables the XMLFormView control to access the InfoPath form's underlying XML data source.

In Solution Explorer, right-click the ModalHost.WebParts project node, and then click Deploy.

Navigate to the page that you created while you were testing the modal dialog box.

Remove the previously added CEWP from the page.

Add the InfoPathFormHost Web Part. (Look for it under the Custom category on the ribbon.)

On the InfoPathFormHost Web Part menu, click Edit Web Part to open the tool pane.

Locate the Configurations category at the bottom of the tool pane, and set Form XSN URL to point to the location where you published the InfoPath form, as shown in Figure 17. (You saved the URL in a text file.)

Figure 17. Tool pane showing the Configurations category

Click OK in the tool pane to close it.

On the ribbon, click Stop Editing button to see the InfoPath form in the browser.

At this point, you have successfully created a browser-enabled InfoPath form, a Web Part to host the form, a search application page to find a document, and a modal dialog box to display the search page. The only task left is to put these components together.

Step 6: Connect the Components

To connect the components, you can start by writing code that makes the XmlFormView control respond to NotifyHost events raised by the form that it hosts. A NotifyHost event occurs when the form's Search button is clicked. You want the host to respond by showing the modal dialog box that displays the search application page. Then, after the dialog box closes and the result of the user's search is posted back to the Web Parts page, additional Web Part code should access the main data source for the InfoPath form and update the hyperlink field by setting its value to the URL of the document that the user selected.

Handling the NotifyHost event

When you created the InfoPath form, you gave it a Search button, and you wrote a button click event handler that calls the NotifyHost(String) method of the XmlForm object. The NotifyHost method accepts a string argument, and you used this argument to pass the XPath for the form field that you want to update.

Now you must prepare the form's host to listen for NotifyHost events and respond by displaying a Search dialog box. Under the hood, you also want to extract the XPath for the form field and put it aside for later use.

You will start by giving the XMLFormView control a NotifyHost event handler. In the handler, you want to do two things:

Add JavaScript to the page so that the next time the page renders in the browser, your modal dialog box appears.

To add a handler for the NotifyHost event

In Visual Studio, open the InfoPathFormHost.cs file in the ModalHost.WebParts project.

Navigate to the CreateChildControls method. Immediately before the line of code that adds the XMLFormView control to the Web Part controls collection, add the following line of code.

// Add a handler for the NotifyHost event.
this.xmlFormView.NotifyHost += new EventHandler<NotifyHostEventArgs>(xmlFormView_NotifyHost);

To define the xmlFormView_NotifyHost method, paste the following code just below the CreateChildControls method.

// Handles the event that is raised when the button
// in the InfoPath form is clicked.
void xmlFormView_NotifyHost(object sender, NotifyHostEventArgs e)
{
try
{
// Check if the argument contains the XPath.
if (!string.IsNullOrEmpty(e.Notification))
{
// Save the InfoPath field XPath in the view state so it can be used later.
ViewState["fieldXPath"] = e.Notification;
// Construct a JavaScript function to invoke the modal dialog box.
StringBuilder functionSyntax = new StringBuilder();
functionSyntax.AppendLine("function popupparams() {");
// Pass the current SharePoint web URL as an argument.
functionSyntax.AppendLine("var url ='" + SPContext.Current.Web.Url + "';");
// Call the JavaScript function to pop up the modal dialog box.
functionSyntax.AppendLine("popupmodalui(url);}");
// Ensure the function popupparams is called after the UI is finished loading.
functionSyntax.AppendLine("_spBodyOnLoadFunctionNames.push('popupparams');");
// Register the script on the page.
Page.ClientScript.RegisterClientScriptBlock(typeof(Page), "ModalHostScript", functionSyntax.ToString(), true);
}
}
catch
{
throw;
}
}

In the event handler, you create and register a script block that defines the JavaScript function popupparams. This function calls the popupmodalui function that we defined earlier in the project (see Step 2: Add JavaScript for the Modal Dialog Box) and passes in the URL for the current page. Then the event handler ensures that popupparams executes when the page body loads by adding it to the _spBodyOnLoadFunctionNames array.

Note

_spBodyOnLoadFunctionNames is a global variable that is defined in the INIT.js file as an array of functions that are registered when a SharePoint page loads. You cannot directly add a function to the onload event for the body of the page because content pages in SharePoint are based on a master page that contains the "body" element. To work around this limitation, SharePoint provides indirect access to the onload event through the _spBodyOnLoadFunctionNames array. When the body of the page is loaded, the onload event handler executes each function whose name is contained in this array.

To finish wiring up the event handler, you must register ModalHost.js on the page. ModalHost.js calls into the JQuery library, so you must also register that. A good place to do the registration is in the handler for the Web Part's OnLoad event.

To register the external script files

In the InfoPathFormHost class, just above the CreateChildControls method, paste the following code that overrides the OnLoad event handler.

The final task is to set the value of the URL field in the form to the URL of the document that the user selects before closing the modal Search dialog box.It may help if you first review the sequence of events:

A user clicks the Search button on the InfoPath form, raising the NotifyHost event on the host Web Part.

Code for the Web Part responds to the event by storing the XPath for the form field in the view state. It then invokes JavaScript that causes the modal dialog box to appear.

The modal dialog box displays an application page with an interface that lets the user search for and select a document.

When the user selects a document, logic in the code behind the search application page places the URL for the selected document in a hidden text box on the application page and enables the OK button in the dialog box.

The commonModalDialogClose method closes the dialog box and passes the URL along to the dialog box's callback function (closecallback in ModalHost.js).

The callback function stores the URL in a hidden text box on the Web Part.

Therefore, to complete the final task, you need code that retrieves the URL from the hidden text box on the Web Part, retrieves the XPath for the field from the view state, and uses both pieces of information to update the value of the field. If the user exits the modal dialog box by clicking OK, the callback function forces a postback that refreshes the page that hosts the form. Therefore, a good place to put code that updates the form is in the Web Part's OnPreRender method.

To add code that updates the URL field

In Solution Explorer, right-click the ModalHost.WebParts project node, and then click Add Reference.

In the Add Reference dialog box, browse to Drive Letter:\Program Files\Microsoft Office Servers\14.0\Bin\Microsoft.Office.InfoPath.dll, and then click OK. If Visual Studio displays a warning message, click Yes, and continue adding the reference to the project.

Open InfoPathFormHost.cs, and add the following using statements at the top of the file.

using System.Xml;
using System.Xml.XPath;

Navigate to the OnPreRender method. Add the following code immediately after the line that sets the EditingStatus property of the XMLFormView control.

// Retrieve the return value from the modal dialog box.
this.receivedValue = this.hiddenText.Text;
// Determine whether the received value is not empty.
if (!string.IsNullOrEmpty(this.receivedValue))
{
// Update the form data source with the new value.
this.UpdateFormMainDataSource();
}

Define the UpdateFormMainDataSource method by adding the following code after the OnPreRender method.

Define the SetFormFieldValue method by pasting the following code after the UpdateFormMainDataSource method.

// Sets the target InfoPath form field value with the received value.
private void SetFormFieldValue(string xpath, string url, string value)
{
// Create an XPathNavigator positioned at the root of the form's main data source.
XPathNavigator xNavMain = this.xmlFormView.XmlForm.MainDataSource.CreateNavigator();
// Create an XmlNamespaceManager.
XmlNamespaceManager xNameSpace = new XmlNamespaceManager(new NameTable());
// Add the "my" namespace alias from the form's main data source.
// Note: Replace the second argument with the correct namespace
// from the form template that you are using.
xNameSpace.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2011-03-29T15:01:42");
// Create an XPathNavigator positioned on the target form field.
XPathNavigator formfield = xNavMain.SelectSingleNode(xpath, xNameSpace);
// Set the form's hyperlink field to the received document URL.
formfield.SetValue(url);
if (formfield.HasAttributes)
{
// Set the hyperlink's display text with document title.
formfield.MoveToFirstAttribute();
formfield.SetValue(value);
}
}

Replace the second argument passed to the AddNamespace method with the correct namespace for your form template. To get the correct value, open the form template in Design mode, and click Show Fields on the ribbon to display the Fields task pane. Right-click myFields, and then click Details.

Press F5 to build and deploy the solution.

This concludes the last phase of application development.

Testing the SharePoint Application

Now it is time to make sure that everything works as expected.

To test the application

Navigate to your SharePoint website in your web browser, and open the Web Parts page where you previously added the InfoPathFormHost Web Part. The form appears as shown in Figure 18.

Figure 18. Contoso Resource Planning form

On the Contoso Resource Planning form, click Search. A modal dialog box should open. The OK button should be disabled, as shown in Figure 19.

Figure 19. Modal dialog box with OK button disabled

Type a search term in the text box, and then click the Search button (magnifying glass). The names of any matching documents should fill the results grid, as shown in Figure 20.

Figure 20. Search results in results grid

Select a document by clicking Select. The row that contains the selected document should be bold, and the OK button should be enabled, as shown in Figure 21.

Figure 21. Selected document in search results grid

Click OK. The dialog box closes, and a link to the selected document appears in the URL field of the form, as shown in Figure 22.

Figure 22. Contoso Resource Planning form with URL added

Conclusion

This article demonstrates how to create a custom Web Part that hosts an InfoPath 2010 browser-enabled form. The article also shows you how to create a handler for the NotifyHost event raised by the form, and how to use the handler to invoke client-side code that opens a SharePoint 2010 modal dialog box. In addition, the article demonstrates how to return a value from a modal dialog box and then use the returned value to update the hosted form.