Introducing InfoPath Form Template Projects

Highlights

In this chapter, you will learn how to

For more information

Overview

To work through this chapter

 SP-1   Several earlier chapters discuss the need to add programming code to Microsoft Office InfoPath 2003 forms to handle tasks that you can t accomplish with InfoPath s declarative programming model. The declarative programming features added by InfoPath 2003 Service Pack 1 (SP-1) ”such as the Insert Formula dialog box, event-based rules, and user roles ”substantially reduce the need to add programming code to forms. The InfoPath 2003 release version supported only JScript or VBScript programming with the Microsoft Script Editor (MSE). SP-1 lets you create InfoPath 2003 Projects, which substitute managed Visual Basic .NET or C# code for script. You must install the Toolkit to take advantage of SP-1 s managed code features.

The chapters in Part IV use Visual Basic .NET for all procedures, because most Office developers are accustomed to writing VBA code to automate Office applications. Visual Basic .NET has full parity with C# as a programming language, although each language has a few features that are missing in the other. For example, Visual Basic .NET supports With ... End With constructs; C# doesn t. C# offers XML comments, which aren t available in Visual Basic .NET. Building .NET assemblies with either language generates identical Microsoft Intermediate Language (MSIL) code, which the just-in-time (JIT) compiler converts to the same machine-language instructions. Neither language offers a significant performance benefit or penalty.

Note  

Programming InfoPath forms with JScript or VBScript

If you re an experienced JScript or VBScript programmer, you might want to apply your scripting skills to form programming. The sample forms installed by InfoPath include JScript event handlers and general-purpose functions that you can use as models for programming your forms. The majority of the InfoPath programming documentation provides JScript ”rather than VBScript ” examples, which is an odd language choice for an Office application. It s much easier for Office developers to apply their VBA skills to VBScript programming than to JScript programming.

Regardless of your scripting experience, Microsoft Visual C# and Visual Basic .NET are Microsoft s preferred programming languages (in that order, unfortunately ), and they represent the future of Microsoft Windows application development. Future versions of InfoPath are likely to be full- fledged .NET implementations ; if so, managed code for implementing business logic probably will be a requirement, not an option.

Comparing Managed NET Code and Script

The primary distinction between managed .NET code and script is how the code executes: .NET code is compiled, and script is interpreted. A language compiler translates .NET source code into MSIL, and the Common Language Runtime (CLR) JIT-compiles the MSIL to executable (machine) code for a specific processor, such as the 32-bit Intel Pentium or 64-bit AMD Opteron series. The JIT compilation process generates machine code on an as-needed basis; the first time a subprocedure or function executes, the JIT-compiled machine code is cached for reuse. An interpreter reads successive lines of script code and translates each line to machine code every time the script runs. In most cases, compiled code executes faster than interpreted code.

The most important benefits of managed code for InfoPath developers are much easier debugging and early object binding, which enables Microsoft IntelliSense in Visual Studio for statement completion. Building and running managed code opens the form in preview mode. When execution reaches a breakpoint, Visual Studio receives the focus to let you determine the value of variables or object properties at that point. Continuing past the breakpoint returns the focus to the form preview. Another advantage of managed code is that your source code isn t easily accessible to InfoPath users or your competitors . The template stores a reference to an assembly , which is a dynamic-link library (DLL) that contains program metadata and MSIL, not source code. Although it s possible to decompile MSIL, you can make it very difficult for others to reverse-engineer your MSIL code with the Dotfuscator obfuscation tool that s included with Visual Studio.

Substituting managed code for script also enables strong typing, which isn t turned on by default for Visual Basic .NET. To enforce strong typing, you must add an Option Strict On statement at the beginning of the code or set a language compiler option to enforce strong typing for all Visual Basic .NET projects. When you declare all variables with their data or object types, the language compiler won t let you set the variable s value to a different type. Strong typing prevents declaring variables of the Object data type, the .NET equivalent of VBA s Variant data type. JScript and VBScript are loosely typed; variables assume the type of the values you assign to them and can change data or object types without notice. Strong typing improves code execution performance and minimizes the potential for run-time errors.

The .NET Framework provides myriad useful classes and methods that aren t present in JScript or VBScript. For example, the InfoPath sample forms require custom getDateString and getTimeString functions to return date and time in the ISO 8601 pattern that s required by fields of the xsd:date and xsd:dateTime datatypes. The .NET Framework s DateTime class provides standard date/time formatters to return ISO 8601, RFC1123, and many other patterns. RFC1123 is the date format used in the RSS 2.0 examples in this and the preceding chapters. The sections Responding to OnAfterChange Events and Taking Action Based on the Value of Another Field, later in this chapter, contain ISO 8601 formatting examples. The section Adding Managed Code to an Existing Form demonstrates RFC1123 formatting.

A minor downside of adding managed code to InfoPath templates is the requirement to install the run-time version of the .NET Framework 1.1 on users computers to provide required classes, and JIT-compile the assembly when the form loads. The 108 MB run-time .NET Framework 1.1 is freely distributable so you can put the  Setup.exe file on a server share and instruct users to install it, or users can download .NET Framework 1.1 from the Microsoft Windows Update site, at windowsupdate.microsoft.com .

Adding Managed Code Behind a Form

After you install the Toolkit, you can add managed code to an imported copy of an existing form or create a new form in Visual Studio s integrated development environment (IDE). When you open the New Project dialog box, you ll find that the Toolkit has added a new Microsoft Office System Projects icon to the Project Types list, which contains subfolders for Visual Basic and Visual C# projects and an InfoPath Form Template icon, as shown in Figure 15-1. (Installing the VSTO also adds this folder and three template icons for Excel and Word 2003.) If you re using Visual Basic .NET Standard, only Visual Basic Projects appear in the list.

Figure 15-1: The Toolkit adds an InfoPath Form Template icon for Visual Basic and, if installed, Visual C#, and supplies default values for the project name and its folders.

Accepting default settings for the project and clicking OK opens the single screen of the Microsoft Office Project Wizard, which lets you choose between importing a copy of an existing form or creating a new form. Importing a form with JScript or VBScript code disables script operation, but the .js or .vbs files remain in the template file for reference when you replace the script s methods with Visual Basic .NET code. If you select the Create A New Form Template option, the project opens with an empty InfoPathProject1 form in design mode in front of Visual Studio s InfoPathProject1FormCode window, as shown in Figure 15-2. Solution Explorer displays the working file set created by the Toolkit.

Figure 15-2: Creating a new form template with the default project name opens a new InfoPathProject1 template in design mode and displays the files added to the project by the Toolkit in Solution Explorer.

The Toolkit adds project references to the System namespace and the Microsoft.Office.Interop.InfoPath.SemiTrust namespace defined by the primary interop assembly DLL of the same name. Microsoft provides primary interop assemblies (PIAs), which are wrappers for Component Object Model (COM) type libraries, for most Office XP and Office 2003 applications. PIAs install in the global assembly cache (GAC) so they can be shared by all .NET projects. Don t infer from the presence of a PIA that an Office application is .NET-enabled; Microsoft Word 2003, Excel 2003, and InfoPath 2003 SP-1 were the only Visual Studio .NET “enabled Office applications when this book was written.

The Toolkit generates Visual Basic .NET code to create instances of the InfoPath Application and XDocument objects in a _Startup event handler. These two objects are the most important members of the InfoPath object model, which is described in detail in Chapter 16. Figure 15-3 shows the default Visual Basic .NET code added by the Toolkit ”commonly called an event-handling stub ”with empty lines removed and minor edits for readability. To have Solution Explorer show all files in the project after building and running the default Visual Basic .NET code, choose Project, Show All Files. Notice that the file set includes multiple references to extracted template files.

Figure 15-3: Running the default Visual Basic .NET code generated by the Toolkit and choosing Project, Show All Files creates the files and file pointers shown here.

Navigating Project Folders

Visual Studio creates all projects in subfolders of your My DocumentsVisual Studio Projects folder by default. If you accept the default values in the New Project dialog box, click OK, select the Create A New Form Template option in the Microsoft Office Project Wizard s only screen, and click Finish, the template generates a set of files and subfolders in a My DocumentsVisual Studio ProjectsInfoPathProject1 folder, which contains only solution (.sln and .suo) files. Your working files, shown in Figure 15-3 s Solution Explorer, are in a nested InfoPathProject1 folder and its subfolders. The files that you deploy after building the project in the default debug mode are located in the My DocumentsVisual Studio ProjectsInfoPathProject1 InfoPathProject1inDebug folder. InfoPathProject1.xsn is the final template file, InfoPathProject1.dll is the managed code assembly, and InfoPathProject1.pdb contains the debugging symbols. When you compile release versions of your projects, .pdb symbols aren t generated.

Changing file names and locations after creating a project is a chancy process at best, so it s a good practice to decide on a final project name and the initial location for the project files before you start a new InfoPath project. Minimizing the length of the project s path makes it easier to check file locations in the file s Properties dialog box. The examples you create in this chapter run from project subfolders of a C:IPProjects projects folder and don t create separate subfolders for the solution (.sln and .suo) files.

Adding an Event Handler to a New Form

Your only access to InfoPath s COM objects that the InfoPath PIA exposes is through event handlers and subprocedures or functions invoked by event handlers. The _Startup event handler of the code behind the form declares two variables ” thisApplication and thisXDocument . These variables represent the current InfoPath form instance and its data source document. XDocument objects contain a UIObject , which has an Alert method to display InfoPath s standard alert message box. A button with a click event handler that opens an alert box is the simplest example of adding event-handling code behind an InfoPath form.

To add a button and an event handler that displays an alert, follow these steps.

Create a new project and add a button event handler

  1. Create a new C:IPProjects folder to store all InfoPath project examples you create in this chapter and in Chapters 16 and 17.
  2. Start Visual Studio, and choose Tools, Options to open the Options dialog box. Select the Environment node s Projects And Solutions item, and change the Visual Studio Projects Location to C:IPProjects. To enforce strong typing with all Visual Basic .NET projects, select the Projects node s VB Defaults item, and set Option Strict to On. Click OK to save your changes.
  3. Choose File, New, Project to open the New Project dialog box, expand the Microsoft Office InfoPath Projects node, and select the InfoPath Form Templates icon.
  4. Change the project s Name to IPEvents.Click More and clear the Create Directory For Solution check box to eliminate one subfolder level, as shown here:

  5. Click OK to close the dialog and open the Microsoft Office Project Wizard, leave the default Create New Form Template option, and click Finish to generate the project and open the IPEvents form in design mode.
  6. Add Option Explicit On and Option Strict On statements above the first Imports statement. It s a good practice to add Option Explicit On and Option Strict On because other programmers who work on your form might not have these defaults set.
  7. Give the focus to the IPEvents template, add a button control, and open its Properties dialog box. Leave the default Rules And Custom Code item in the Action drop-down list, change the Label value to Click Event Test, and set the ID value to btnClickEvent, as shown here:

  8. Click the Edit Form Code button to add the button s OnClick event handler to the IPEvents class as a Visual Basic subprocedure and return the focus to Visual Studio.
  9. Replace the ˜Write your code here comment in the event handler with
  10. thisXDocument.UI.Alert("Button OnClick event handler"), and observe the property and method options as you type each period.
  11. Press F5 to build and run the project, and click Yes in the message box, which opens a preview of the IPEvents form.
  12. Click the button to display the message in a standard InfoPath Alert message box, as shown here:

Note  

Restoring InfoPath templates that disappear

If you accidentally close the current InfoPath template instance, choose Tools, Open InfoPath or Project, Open InfoPath to restore it.

The event handler s < InfoPathEventHandler (MatchPath:="btnClickEvent", EventType:=InfoPathEventType.OnClick) > attribute delegates handling of the InfoPath OnClick event to the btnClickEvent_OnClick event handler. The e parameter s DocActionEvent interface has three properties: ReturnStatus , Source , and XDocument . The ReturnStatus property is a Boolean value that defaults to True and is useful for handing InfoPath events that accept return values and cancel the action if the return value is False . The Source property returns a read-only IXMLDOMNode instance that represents the form s current data source ” my:fields for the example at this point.

Note  

Copying and pasting code snippets

Your C:Microsoft PressIntroducing InfoPath 2003Chapter15IPEvents folder has text files that contain the code snippets you add to the event-handling procedures in the remaining exercises in this chapter. The file name is provided in the step that describes the code to be added.

The UI object s Confirm method provides the visual equivalent of a Windows forms message box and offers a choice of OK/Cancel, Yes/No, or Yes/No/Cancel buttons . You can use the return value of the message box to control program flow with an If ... Else ... End If construct. To change the alert to a confirmation message box, replace the alert statement you added in step 9 of the preceding procedure with the following statements or add them from Confirm.txt:

With thisXDocument If .UI.Confirm("The source is " + e.Source.baseName + _ ". Do you want to continue?", XdConfirmButtons.xdYesNo) = _ XdConfirmChoice.xdYes Then e.ReturnStatus = True .UI.Confirm("Continuation confirmed.", _ XdConfirmButtons.xdOKCancel) Else e.ReturnStatus = False End If End With

When you click the button, the upper confirm message box of Figure 15-4 opens. Click Yes to open the message box. Unfortunately, the Confirm method doesn t offer a single OK button choice to provide a more compact version of an alert.

Figure 15-4: Clicking Yes in the first (upper) confirm message box displays the lower one.

Working with Data Source Field Events

Changing data source field values or adding and deleting repeating form sections triggers the following three events:

Adding field event handlers requires a data source and controls to change values. Follow these steps to convert the data source of your form to a simple XML document with fields of multiple data types, and add controls to the form s layout table.

Add a data source and controls to the form

  1. In the form s design view, choose Tools, Convert Main Data Source to start the Data Source Wizard.
  2. In the first wizard screen, click Browse, and open C:Microsoft PressIntroducing InfoPath 2003Chapter15IPEventsEventsData.xml. Click Next, and then click Finish to substitute the EventData document structure and its default values for the empty my:fields data source. Click Yes in the message box that asks whether you want to update expressions automatically. Replacing the data source adds several new namespaces to the Public Class IPEvents attribute.
  3. Open the Data Source task pane, change the data type of the date1 field to Date (date) and the dateTime1 field to Date And Time (dateTime), and change the remaining fields ending in 1 to the data type represented by their name . Leave all fields ending in 2 as the default Text (string) data type.
  4. Add a two-column, five-row layout table under the button, and drag the element fields to the table cells in left-to-right , top-to-bottom sequence. Drag the eventType attribute to the right of the button to add a label and text box.
  5. Click Preview This Form, click Yes if the message box asks whether you want to update expressions in the code, and then click Preview This Form again to build and run the project. Your form preview appears as shown here:

Responding to OnAfterChange Events

True/False (Boolean) fields are a good choice for an initial OnAfterChange event- handler coding exercise, because the code is very simple. The event handler updates the value of the Boolean 2 text box with a value that corresponds to the state of the Boolean 1 check box. You specify the target node ”an IXMLDOMNode object ”by applying the thisXDocument.DOM.selectSingleNode("/eventsData/boolean2") method and then setting the target node s text property value to the text property value of the event handler s e.Source parameter. The code detects the e.operation = Delete condition and exits, so only Insert operations are processed .

It s a good programming practice to add structured exception handling to any event handler that might generate a run-time error, because InfoPath projects disregard some run-time exceptions. In this case, your code fails silently, and you might overlook an occasional or even a repetitive exception. Adding a stack trace to the error handler s message supplies the line number on which the error occurred.

Follow these steps to complete the boolean1 event handler with a Try...Catch...End Try block for exception handling.

Add an event handler for the boolean2 field

  1. Close the preview window to return to design view. Right-click the boolean1 field in the Data Source list, and choose Properties from the shortcut menu to open its Properties dialog box. Click the Validation And Event Handlers tab, and select OnAfterChange in the Events drop-down list, as shown here:

  2. Click Edit to add the boolean1_OnAfterChange event handler to the code and return the focus to Visual Studio, as shown here:

  3. Remove the empty lines and, optionally , the comments, and add the following code from Boolean1.txt after the event handler s End If line to update the boolean2 field with the state of the Boolean 1 check box:

    If e.Operation = "Delete" Then Return End If Try Dim nodTarget As IXMLDOMNode = _ thisXDocument.DOM.selectSingleNode("/eventsData/boolean2") nodTarget.text = e.Source.text Catch excBool As Exception thisXDocument.UI.Alert(excBool.Message + _ excBool.StackTrace.ToString) End Try

  4. Press F5 to build and run the project and open a preview window, and test the event handler by clicking the Boolean 1 check box a few times.
  5. Give Visual Studio the focus, position the insertion point on the first If line, and press F9 to set a breakpoint.
  6. Give the preview window the focus, and then change the Boolean 1 check box s state and halt execution at the breakpoint. Press F11 to step through the procedure, observe that the event fires twice but is processed only once, and then clear the breakpoint by pressing F9 on the highlighted line or by choosing Debug, Clear All Breakpoints.

Nillable Date ( date ) and Date And Time ( dateTime ) fields present a challenge when you need to convert the Variant data type (Object) of dates returned by the event handler s e.Source.nodeValue property to the DateTime data type, which enables easy ISO 8601 formatting with the ToString( s ) method and date arithmetic. To avoid run-time errors, you must test for e.Source.text values that result from entering empty date values in the date picker s text box.

To create the date1_OnAfterChange event handler, follow these steps.

Add an event handler for the date1 field

  1. Repeat steps 1 and 2 for of the preceding procedure for the date1 field.
  2. Add the following code from Date2.txt after the event handler s End If line to update the date2 field with the date you select in the date1 date picker control:

    If e.Operation = "Delete" Then Return End If 'Specify date1 as the field to be updated Dim nodTarget As IXMLDOMNode = _ thisXDocument.DOM.selectSingleNode("/eventsData/date2") If e.Source.text = "" Then 'Date is nil nodTarget.text = "" Try 'Format the DateTime object as ISO 8601 Dim strDate As String = _ CType(e.Source.nodeValue(), DateTime).ToString("s") 'Remove the time value nodTarget.text = Left(strDate, InStr(strDate, "T") - 1) 'Select the eventsData node nodTarget = nodTarget.parentNode 'Set the attribute value nodTarget.attributes(0).text = "date1 Changed" Catch excDate As Exception 'Catch runtime errors thisXDocument.UI.Alert(excDate.Message + _ excDate.StackTrace.ToString) End Try

  3. Press F5 to build and run the project and open a preview. Select a date, and verify that the Date 2 text box displays an ISO 8601 date.
  4. Add a breakpoint at the second If statement, and clear the Date 1 text box. Press F11 to step through the procedure, which executes three times, and then clear the breakpoint.

If you want to see an exception-handling alert, comment the second Return statement, add a date value, clear the date value, and press Tab. You ll receive two error messages similar to the one shown in Figure 15-5.

Figure 15-5: A common source of InfoPath event-handler exceptions is attempts to cast a nondate Variant value to the DateTime type, as illustrated by this alert.

Handling OnBeforeChange Events

The OnBeforeChange event lets you intercept changes, apply business logic to the proposed new value, let users decide whether to make the change with a confirm message box, send a ReturnMessage to an alert message box, or any combination of these actions. Your code must handle multiple events correctly to avoid reoccurring confirm message boxes. In this procedure, a blnHasChanges flag determines whether the value has been changed by a previous OnBeforeChange Insert event. This procedure s event- handler code isn t prone to run-time errors, so exception handling isn t implemented.

Follow these steps to add the dateTime1_BeforeChange event handler.

Add an OnBeforeChange event handler for the dateTime1 field

  1. In InfoPath design view, right-click the dateTime1 field in the Data Source task pane, and choose Properties from the shortcut menu to open its Properties dialog box. Click the Validation And Event Handlers tab, and select OnBeforeChange in the Events drop-down list.
  2. Click Edit to add the dateTime1_OnBeforeChange event handler to the code and return the focus to Visual Studio.
  3. Remove the empty lines and, optionally, the comments, and add a Private blnHasChanged As Boolean statement immediately after the Private thisApplication As Application statement.
  4. Add the following code from DateTime2OBC.txt after the event handler s End If line to display a confirm message box with Yes/No buttons and an alert if the user elects to abandon the changes:

    If e.Operation = "Delete" Then Return End If If blnHasChanged Then blnHasChanged = False Return End If If thisXDocument.UI.Confirm("Do you want to update " + _ "dateTime2 and dateTime1?", XdConfirmButtons.xdYesNo) = _ XdConfirmChoice.xdYes Then e.ReturnStatus = True True blnHasChanged = 'Cancel the update e.ReturnStatus = False blnHasChanged = False e.ReturnMessage = _ "DateTime updates were canceled by the user." End If

  5. Press F5 to open a preview, and change the Date Time 1 date picker value to open a confirm message box. Click No to display the alert with the return message.
  6. Add a breakpoint at the first If statement, change the date, and trace execution to verify that the event fires twice but is processed only once. If you delete the date in the text box and press Tab, the event executes three times, but the flag prevents the confirm message from appearing twice.

Taking Action Based on the Value of Another Field

The following procedure displays ISO 8601 “formatted date and time values for local time or Universal Time Coordinate (UTC) in the Date Time 1 text box, depending on the state of the Boolean 2 check box. The code is similar to that for the date2_OnAfterChange event handler, except for addition of the boolean2 field value test and code to change local to UTC time, as shown here:

Dim datNodeValue As DateTime = _ CType(e.Source.nodeValue(), DateTime) Dim strNodeValue As String 'Get the value of the boolean2 node Dim nodIsUTC As IXMLDOMNode = _ thisXDocument.DOM.selectSingleNode("/eventsData/boolean2") If nodIsUTC.text = "true" Then 'Use Universal Coordinated Time strNodeValue = datNodeValue.ToUniversalTime.ToString("s") Else 'Use local time strNodeValue = datNodeValue.ToString("s") End If

To add the dateTime1_OnAfterChange event handler, follow these steps.

Add an OnAfterChange event handler for the dateTime1 field

  1. Close the preview window to return to design mode. Right-click the dateTime1 field in the Data Source task pane s list, and choose Properties from the shortcut menu to open its Properties dialog box. Click the Validation And Event Handlers tab, and select OnAfterChange.
  2. Click Edit to add the dateTime1_OnAfterChange event handler to the code and return the focus to Visual Studio.
  3. Paste the code from DateTime2OAC.txt after the event handler s End If line to set the value of the dateTime2 field.
  4. Test the event handler with Date Time 2 date picker values and empty dates. Clicking the Boolean 1 check box to change the date format. The form, with a UTC date and time, appears as shown here:

  5. Optionally, set a breakpoint, and trace execution of the code when you change a Date Time 1 value.

Adding Managed Code to an Existing Form

Creating a new InfoPath project from an existing template is a simple, two-step process if your form doesnt incorporate JScript or VBScript code. Moving to managed code disables the script, and you must rewrite all event handlers in Visual Basic .NET or C#. If your template contains more than 100 lines of script, conversion probably isnt justified unless you need to implement features that the .NET Framework supports and script doesnt. As an example, you need the .NET Framework and the Microsoft Web Services Enhancements (WSE) 2.0- add-on to connect to secure Web services that implement SOAP message encryption and require digital signatures. Digitally signed SOAP messages supplementbut dont replacedigital signatures applied to forms.

RSS 2.0 data documents have a repeating item section with a pubDate field that requires a RFC1123-formatted date string. Repeating sections introduce you to the use of the IXMLDOMNodeList object, which contains a collection of repeating IXMLDOMNode elements. The objects length property returns the number of instances of the repeating section. You can specify the instance you need by an index thats less than the length valuefor example, NodeList1(NodeList1.length -1) points to the last section.

Adding the current time in RFC1123 format when inserting a new section improves data entry efficiency and minimizes typographic errors. The DateTime.UtcNow property returns the current UTC time, and the ToString(R) method returns the RFC1123 pattern. Its a common practice to add RSS 2.0 items in reverse date/time order (last in, first out) with Insert Above operations, but users can insert new sections in any arbitrary sequence. Thus your code must test all sections for the presence of a pubDate field value and add the current date/time value if its missing.

To add the RFC1123 date and time to a copy of the Rss2v4.xsn template from Chapter 10, Adding Views to a Template, follow these steps.

Create the Rss2v4Events project and add the event-handling code

  1. Start Visual Studio, and choose File, New, Project to open the New Project dialog box. Click the InfoPath Form Template icon, type Rss2v4Events as the Name and, if you didnt set the default folder, type C:IPProjects as the Location.
  2. Click OK to open the Microsoft Project Wizard. Select the Open Existing Form Template option, click Browse, navigate to C:Microsoft PressIntroducing InfoPath 2003Chapter15Rss2v4Events, and double-click Rss2v4 (Ch10).xsn.
  3. Click Finish. In the message box that appears, assuring you that the original template wont be modified, click OK to open the FormCode.vb window and an InfoPath design mode instance.
  4. Add Option Explicit On the Option Strict On as the first two lines of code.
  5. Activate the Data Source task pane, right-click the item section in the Data Source task pane list, and choose Properties from the shortcut menu to open the Properties dialog box. Click the Validation And Event Handlers tab, select the OnAfterChange event, and click Edit to add the item_OnAfterChange event handler.
  6. Add the following code from Rss2v4Events.txt, which is located in the same folder as the original template, below the End If statement:

    If e.Operation = "Delete" Or e.Site.nodeName <> "item" Then Return End If Try Dim strXML As String = e.Source.xml 'Create a list of pubDate node(s) Dim lstItems As IXMLDOMNodeList = _ e.Source.selectNodes("//pubDate") 'Check all pubDate nodes Dim intItem As Integer For intItem = 0 To lstItems.length - 1 Dim nodLastItem As IXMLDOMNode = lstItems(intItem) nodLastItem.selectSingleNode("//pubDate") If nodLastItem.text = "" Then 'Get current system time as UTC if pubDate is empty Dim datNow As DateTime = DateTime.UtcNow 'Add the RFC1123 date nodLastItem.text = datNow.ToString("R") End If Next intItem Catch excInsert As Exception thisXDocument.UI.Alert(excInsert.Message + _ excInsert.StackTrace) End Try

  7. Press F5 and click Yes to build the project and open a preview window. Insert sections above, below, and between other sections to verify that the event handler performs as expected, as shown here:

The e.Site.nodeName <> "item" test in the first statement verifies that the event originated from inserting an item node and not from the change to the pubDate field value. Events lower in the XML documents hierarchy percolate to the root element, a process called event bubbling . For more information about the Site object and event bubbling, search the InfoPath SDK Documentation for the term bubbling (include the quotation marks).

Managing Project Relocation and Deployment

The following sections show you how to handle errors that occur when you open a form from a project template in a location other than the ProjectName folder, change the location of the InfoPath project files, create a release version of your template, and publish production templates.

Dealing with Template Cache Conflicts

You can create and save a sample data document from the Fill Out A Form task pane in the project s InfoPath design window. In this case, InfoPath use the manifest.xsf file in the project folder as the template and adds it to the local form template cache. Alternatively, you can emulate opening a production Form1 by double-clicking the template file that contains the project s assembly DLL ”IPEvents.xsn for this example ”in the ... ProjectName inDebug folder. Opening Form1 from this folder displays the Form Conflict dialog box shown in Figure 15-6. If you re developing the form template, click the Keep Form On Your Computer button to use the manifest.xsf version. After you complete the form s design, click the Replace Form On Your Computer button to use the FormName.xsn template.

Figure 15-6: This message box appears when you attempt to open a new Form1 from the template s .xsn file in the ...inDebug folder and the manifest.xsf version of the template is in the local cache.

Copying an InfoPath Project to a New Location

Visual Studio users appreciate easy XCopy deployment of their Windows and Web forms projects; moving an entire InfoPath project to a new folder is as easy as using Save As with a conventional template. You can copy the entire project folder to another location and continue development without making any changes to the project. When you open the project, you might receive a warning message that advises you to publish the form from its new location. You can ignore the warning message prior to creating a release version of the project and publishing the template for production use.

Creating a Release Version of the Project

By default, Visual Studio creates and runs InfoPath projects in debug configuration. The debug version of the assembly ( ProjectName .dll) is slightly larger than the release version, and debug versions of large projects execute more slowly than release versions. The debug symbols (.pdb) file adds unnecessary bulk to the template file. Before you publish a production form, create the release version by choosing Build, Configuration Manager to open the Configuration Manager dialog box. Select Release in the Active Solution Configuration drop-down list, as shown in Figure 15-7, and click OK.

Figure 15-7: Changing the InfoPath project s configuration from Debug to Release generates a production version of the project without a ProjectName .pdb file.

Run the project to create a ... ProjectName inRelease folder, which contains release versions of your template and its assembly. The completed projects in your C:Microsoft PressIntroducing InfoPath 2003Chapter15IPEventsIPEvents and ...Rss2v4EventsRss2v4Events folders have debug and release versions. Debug is the default configuration for these projects.

Publishing Forms with Managed Code

The process of publishing an InfoPath template with managed code to shared folders, Web sites, and SharePoint forms libraries is identical to publishing a template with or without script. Choose Tools, Publish Form to build the form and start the Publishing Wizard. Complete the wizard s steps, as described in Chapter 12, Publishing Form Templates. The template file contains the assembly DLL. InfoPath publishes your template s release version, if it exists; if not, InfoPath publishes the debug version.

Like forms containing script or ActiveX controls, Domain is the default security mode for forms containing managed code. If your code accesses local computer resources outside of the form, requires cross-domain permissions, or includes references to custom .NET assemblies that aren t signed by Microsoft, you must specify Full Trust as the security mode and specify a code signing certificate to digitally sign the form on the Security tab of the Form Options dialog box. Alternatively, you can deploy a custom-installed template to users computers.

Summary

InfoPath projects substitute .NET managed code for script to implement business logic that declarative programming cant handle. You must have Visual Basic .NET 2003 Standard or Visual Studio .NET 2003 Professional or later and the Toolkit for InfoPath 2003 installed to create InfoPath projects with Visual Basic .NET code. This book uses Visual Basic .NET for all programming examples, because Office developers can leverage their VBA skills to write InfoPath event handlers and utility functions or subprocedures.

The Toolkit creates an event-handling subprocedure stub with default code when you specify an event handler by choosing Tools, Programming. Clicking Edit with an event selected on the Validation And Event Handlers tab of a field or sections Properties dialog box also generates a stub. You add code to implement business logic to the stub to complete the event handler. Adding structured exception handling to the code you write ensures that you catch run-time errors that otherwise might not be evident.

Debug is Visual Studios default configuration for InfoPath projects. To publish a production InfoPath project, you use the Configuration Manager to change to Release configuration, and rebuild your project. You publish the project by choosing Tools, Publish Form in Visual Studio to run InfoPaths Publishing Wizard. The resulting .xsn file includes the .NET assembly that contains the projects MSIL code. Users must have the .NET Framework 1.1 runtime installed on their computers to JIT-compile the MSIL to executable code.

Q A

1.  

Does InfoPath trigger more than the three events discussed in this chapter?

2.  

Why do InfoPath projects require programming MSXML objects rather than .NET s more versatile System.Xml classes?

3.  

Can I use .NET s System.Xml classes to manipulate the data document independent of InfoPath?

4.  

Are there any other InfoPath UI objects that I can program with .NET code?

Answers

1.  

Yes, but OnBeforeChange , OnValidate , and OnAfterChange are the most frequently used event handlers in InfoPath projects. The Programming option on InfoPath s Tools menu provides On Load Event, On Switch View Event, On Context Change Event, and On Sign Event items, which generate the corresponding event handlers. The OnSubmitRequest and OnVersionUpgrade events let you write code to customize the form submission and upgrade processes. SP-1 adds several more events to InfoPath s repertoire ; the next two chapters have code examples for the events not covered in this chapter.

2.  

InfoPath 2003 SP-1 is a conventional Windows application that exposes COM objects to provide access to Application and XDocument objects. You re limited to manipulating InfoPath COM objects that managed code accesses through the InfoPath PIA. InfoPath, not MSXML, provides the IXMLDOM interfaces that you program with .NET code. SP-1 exposes its classes and interfaces as Automation objects, so Visual Basic 6 or VBA code can manipulate InfoPath objects by adding a reference to the Microsoft InfoPath 1.0 Type Library.

3.  

Yes, you can retrieve the cached XML document s contents as a String at any point in the editing process with a thisXDocument.DOM.xml instruction. After you add a reference to System.Xml.dll and an Imports System.Xml statement to InfoPath s default FormCode.vb, you can populate an in-memory XmlDocument instance with a docXML.LoadXml(thisXDocument.DOM.xml) statement. You can modify docXML , navigate it with an XPathNavigator object, import it to a DataSet (if the document is relational), and transform it with Extensible Stylesheet Language Transformation (XSLT). Your form must be fully trusted to save the modified document to an .xml file with the XmlTextReader class.

4.  

Yes. The XDocument.UI object provides a ShowModalDialog method that displays a dialog box that you define using a conventional HTML file, which can contain script. The form must be fully trusted to open the dialog box. The InfoPath 2003 SDK s documentation offers additional implementation details for the method; type showmodaldialog as the search term and follow the links. You also can display the e-mail message and signature dialog boxes with the ShowMailItem and ShowSignatureDialog methods .

On Your Own

Heres an additional exercise that uses the Rss2v4Events.xsn template to demonstrate event-handling code reuse:

  1. Open the Default Values dialog box, and select the item field check box to make one item instance required.
  2. Open a preview window, and observe that the Pub Date text box is empty, because the OnAfterChange event doesnt fire in this case.
  3. Choose Tools, Programming, On Load Event to add an OnLoad event-handling stub.
  4. Copy the Try...Catch...End Try block only from the item_OnAfterChange event handler to the OnLoad stub. The OnLoad event fires once when you open the form, so you dont need the tests that precede the Try statement.
  5. The DocReturnEvent parameter doesnt provide an OnLoad property, but it does have an XDocument property that serves a similar purpose. Change the Dim lstItems As IXMLDOMNodeList = e.Source.selectNodes("//pubDate") statement to Dim lstItems As IXMLDOMNodeList = e.XDocument.DOM.selectNodes ("//pubDate") to substitute XDocument for Source .
  6. Open a preview window, and verify that the Pub Date text box now displays the current date and time.

Категории