Navigating the InfoPath Object Model

Highlights

In this chapter, you will learn how to

For more information

Overview

To work through this chapter

 SP-1   All Microsoft Office System 2003 applications provide Component Object Model (COM) object or type libraries to expose internal application objects to script, Microsoft Visual Basic for Applications (VBA), Visual Basic 6, and .NET programming languages. Object models depict the hierarchy of the application s exposed objects; for Office objects, the top member of the hierarchy is the Application object. All other objects are descendants of the Application object and represent either individual objects or object collections. Gaining access to an Office application s object or type library from VBA or Visual Basic 6 code requires adding a reference to the library to enable both early binding and the Microsoft IntelliSense feature. Most Office applications export the library from their executable files ”for example, Excel.exe exports the Microsoft Excel 11.0 Object Library. As you learned in the section Adding Managed Code Behind a Form, in Chapter 15, .NET-enabled Office 2003 applications ”Microsoft Excel, Word, and InfoPath ”use primary interop assembly (PIA) type library wrappers to manipulate the Application object and its descendants.

The purpose of an object model diagram is to provide developers with a shortcut to understanding the object hierarchy and to finding objects to fulfill a specific programming requirement. InfoPath s object model is much simpler than that of Access, Excel, or Word. Excel s object model occupies four lengthy Web pages, and Word s takes up seven pages; InfoPath s object model fits on a single page. The InfoPath release version exposed ExternalApplication as a COM Automation object; only internal JScript or Microsoft Visual Basic Scripting Edition (VBScript) could access other InfoPath objects. The ExternalApplication object s primary purpose was to enable local registration of custom-installed forms. InfoPath SP-1 exposes its entire object hierarchy as Automation objects and through the InfoPath PIA.

Despite the relative simplicity of InfoPath 2003 s object model, it s impossible to provide detailed descriptions and examples of all its members in a single chapter of reasonable length. The original InfoPath SDK required more than 200 pages of varying length to document and provide trivial JScript code examples for the object model s collection, object, property, method, event, and enumeration elements. InfoPath SP-1 adds about 100 new elements to the list. Thus, this chapter concentrates on object model elements that are most commonly used in programming InfoPath forms, with emphasis on elements added by SP-1.

Getting Acquainted with Visual Studio s Object Browser

To display the Object Browser, open an InfoPath 2003 project, such as one of those you created in Chapter 15, and choose View, Object Browser or press Ctrl+Alt+J to add a tab to the main window of the integrated development environment (IDE). Figure 16-1 shows the floating version of Object Browser displaying members of the Application class. Visual Studio .NET s Object Browser is similar to that of Visual Studio 6, but it displays a different hierarchy in the Objects pane: Project or Assembly, Namespaces, and (if you right-click in the Objects pane and choose Group By Object Type) Classes, Interfaces, Enums, and Delegates. The Members pane lists the selected object s properties and methods with their arguments, data types, and return data types. The bottom pane displays a more detailed version of a selected member s calling syntax.

Figure 16-1: The Visual Studio .NET Object Browser s four-level Objects hierarchy doesn t display the hierarchical relationship of classes.

Following are brief descriptions of the four object types provided by the InfoPath PIA:

Object Browser s usefulness to InfoPath programmers is hampered by its lack of a hierarchical view of classes to display object relationships. InfoPath class names , except Application , have the object class type appended, such as WindowObject and WindowsCollection . You refer to these objects in code without the class type suffix ” Window and Windows .

Working with the Application Object

The Application object is the root of the object hierarchy in InfoPath and it provides access to all other objects that the InfoPath PIA exposes. Figure 16-2 shows the top part of the InfoPath SDK s object model diagram. The XDocuments collection, which includes an XDocument member for each open form, is the most important Application object member. XDocument objects, which you programmed as thisXDocument in Chapter 15, are the subject of this chapter s later sections.

Figure 16-2: The Application object s high-level methods and properties are used primarily to determine the current state of the InfoPath project. Event handlers provide the current XDocument object as a member of the e ( eventArgs ) argument.

Tables 16-1 and 16-2 describe the Application object s most commonly used properties ”including child objects ”and methods; an asterisk identifies items added by InfoPath 2003 SP-1. For information about other properties and methods, click Application in the InfoPath 2003 SDK s object diagram, and then click the Properties or Methods links to open a list of links to applicable help topics.

Table 16-1: Selected Properties of the Application Object

Property

Description

MachineOnlineState*

Returns an EnumMachineOnlineState enumeration that has one of the following values: Online , Offline , or IEIsInOfflineMode . The latter two states indicate that the network isn t available.

UsableHeight*, UsableWidth*

Returns the maximum value in pixels to which you can set the Window.Height and Window.Width properties (Integer).

Window.Height*, Window.Width*

Gets or sets the specified window s height and width in pixels (Integer).

Window.Top*, Windows.Left*

Gets or sets the specified window s top and left margins in pixels (Integer).

User .IsCurrentUser (strLogin)*

Returns True if the login specified by strLogin (in DOMAINUserName format) is the currently logged in user.

User.IsUserMemberOf (strGroup)*

Returns True if the currently logged in user is a member of the security group specified by strGroup (in DOMAINGroupName format).

ActiveWindow.WindowType

Gets or sets an XdWindowType enumeration that has one the following values: xdDesignerWindow or xdEditorWindow . During debugging, the value returned by inspecting this property in the OnOpen event handler is xdDesignerWindow , if the preview window isn t open when you build the project.

ActiveWindow.Caption

Returns the window name from the title bar, such as Preview1 or Form1. During debugging, the value in the OnOpen event handler is Nothing .

Table 16-2: Selected Methods of the Application Object

Method

Description

IsDestinationReachable (strURL)*

Tests for network connectivity to a server specified by a UNC path to a shared folder, such as \OakLeaf-W2K3Shared, or the URL for a Web site or virtual directory,to a shared folder, such as http://www.oakleaf.ws/infopath . The strURL argument must contain the share name for UNCs ”for example, \OakLeaf-W2K3 fails with an exception. IP addresses and URLs require a fully trusted form, because the domain can t be predetermined. The method returns True if the network resource is accessible.

Quit (blnForce)

Closes the current InfoPath instance. If blnForce is False , the default, a message prompts users to save changed (dirty) forms. If blnForce is True , InfoPath closes immediately without saving changes.

CacheSolution (strURI)*

Checks the currency of a published form s cache and updates the local cache from the published location, if necessary.

The C:Microsoft PressIntroducing InfoPath 2003Chapter16Rss2Events (Ch11) folder contains text files of sample Visual Basic .NET code and a starter Rss2Events project for this chapter s proceduresCh11. Each of the form s two views has a button; you add event handlers for the buttons later in this chapter.

The following code from OnLoadAppCode.txt illustrates the use of several new Application.User properties and methods described in Table 16-1:

'Application properties and methods examples With thisApplication 'Check network connectivity Dim blnOnline As Boolean If .MachineOnlineState = EnumMachineOnlineState.Online Then blnOnline = True 'Check network resource availability Dim blnLAN As Boolean = _ .IsDestinationReachable("OakLeaf-W2K3Shared") Dim blnWeb As Boolean = _ .IsDestinationReachable("www.oakleaf.ws/infopath/") Else 'Warn user and disable operations that require 'a network connection End If 'Check user identity and group membership 'Change OAKLEAF to your domain name With .User Dim blnIsUserAdmin As Boolean = _ .IsCurrentUser("OAKLEAFAdministrator") Dim blnIsGroupIPDesigners As Boolean = _ .IsUserMemberOf("OAKLEAFInfoPathDesigners") Dim blnIsGroupIPUsers As Boolean = _ .IsUserMemberOf("OAKLEAFInfoPathUsers") 'Logic to restrict user activities based on user name and/or 'group membership goes here End With 'Return the InfoPath majorversion.minorversion.build Dim strVersion As String = .Version End With

This code tests network connectivity, so code in the first If block won t execute if you re not connected to a local area network (LAN) or the Internet. The Application.User method supplements the XDocument objects s Role property, which returns the name of the role assigned to the current user.

To add the code to the OnOpen event handler and test the values, follow these steps.

Add and test application properties and methods

  1. Navigate to your C:Microsoft PressIntroducing InfoPath 2003Chapter16Rss2Events (Ch11)Ch11 folder, and double-click Rss2Events.sln to open the project.
  2. Press F5 to build and run the project, choose View, All Sections to display the alternative view, and then close the preview window.
  3. In Notepad, open OnLoadAppCode.txt from the project s parent folder with Word Wrap off, and copy and paste the code below the OnLoad event handler s Try statement.
  4. In the first If block, change \OakLeaf-W2K3Shared to an accessible shared folder.
  5. In the With .User block, change OAKLEAF to your domain name or, if you re not a member of an ActiveDirectory domain, to your computer name. Change login and group names to suit your computer s configuration.
  6. Select the Try statement, and press F9 to add a breakpoint.
  7. Press F5 to execute the code to the breakpoint.
  8. Press F11 to step through the code to the Dim blnLAN statement, and pass the mouse pointer over the blnLAN variable name, which displays blnLAN = True .

    The code you paste from OnLoadAppCode.txt has some additional statements to make inspecting the values easier.

  9. Continue stepping through the code, stopping at the End With statements and checking the variable values, which are visible only within the code block in which you declare them. The last With block doesn t display values.
  10. Press F5 to continue execution, verify the size and state of InfoPath s design window, and close the preview window.

You ll add event handlers for the buttons and set the size and state of the InfoPath window later in the chapter.

Exploring the XDocument Object

Figure 16-3 shows the InfoPath SP-1 XDocuments object model. The thisXDocument variable and most event-handling stubs e ( eventArgs ) argument return a reference to the XDocument object whose form is being edited and has the focus. The most common use of XDocuments is to determine the number of simultaneously open forms and their properties, such as Caption .

Figure 16-3: InfoPath SP-1 adds three collections and nine objects to the XDocument object. The DataAdapters collection replaces the InfoPath release version s more complex DataObjects collection.

Table 16-2 describes the XDocument object s top-level collections and objects and selected child objects. An asterisk denotes elements added or enhanced in InfoPath SP-1.

Table 16-3: Top-Level Collections and Objects of the XDocument Object

Collection or Object

Description

DOM

Returns an IXMLDOMDocument instance that represents the complete XDocument object as a tree of XML nodes. The xml property returns a String that you can manipulate with Visual Basic .NET procedural code. Chapter 17 provides IXMLDOMDocument programming examples.

Errors

Contains Error objects that result from schema or data validation failures. Error object properties return detailed information about the source and reason for the failure.

Extension

Returns global script values and provides access to functions in JScript or VBScript files, but not to functions in managed code.

Solution

Has properties that provide information about the Manifest.xsf file; the DOM property returns an IXMLDOMDocument instance of the file.

DataObjects

Provides access to the release version s DataAdapter objects.

SP-1 s DataAdapters collection replaces and makes obsolete the DataObjects collection.

DataAdapters*

Contains members for DataAdapter objects, which represent main and secondary data source instances that you create with the Data Connection Wizard. Chapter 17 provides customizing data connection examples.

SignedDataBlocks*

Contains SignedDataBlock objects for each data block that has a digital signature. This object has a Signatures collection of Signature objects, which contain information about an individual signer of the data block, and a Certificate object that provides details about the signer s certificate. The OnSigned event returns a SignEvent object, which represents a new SignedDataBlock object.

Util

Provides Math and Date child objects and a Match method to test field values against a regular expression. Chapter 17 provides examples of complex regular expressions in schemas and for data validation.

Util.Math*

Provides access to the aggregate functions of the Insert Formula dialog box ” Avg , Min , Max , and Eval ” which take an IXMLNodeList object as their argument. Eval lets you evaluate an expression, as in Util.Math.Avg(Util.MathEval(IXMLNodeList, UnitPrice * Quantity *

(1 - Discount) ) , to sum OrderDetails items. Util.Math also provides an Nz (null-to-zero) function to convert nodes without content to 0 for calculations.

Util. Date*

Provides Today and Now functions to return the system date and date/time values as ISO 8610 “formatted strings.

UI*

Provides access to the Alert and Confirm message boxes you programmed in Chapter 15 and ShowModalDialog and ShowSignatureDialog methods to display custom and Digital Signatures dialog boxes. The new SetSaveAsDialogLocation and SetSaveAsDialogFileName methods let you specify the default path and file name for the Save As dialog box.

View

Represents the active form s current view. The View.Window property returns a Window object for the current view, which has the same collection and object members as Figure 16-2 s Application.Windows.Window object. The most commonly used members of the View object are its SwitchViews method and its View.Window.TaskPanes(0). HTMLDocument for changing the HTML content of a custom task pane.

ViewInfos

Contains a ViewInfo object for each view of the current form, which provides IsDefault and Name property values.

Tables to fully describe all objects, methods, and properties of the XDocument object would require a book of their own. Instead, the procedures in this chapter s remaining sections and Chapter 17 s more advanced procedures show you how to program the most commonly used XDocument elements.

Working with View Objects and Events

You can make changing views easier for users by adding buttons to execute the SwitchView(ViewName) method. The Rss2Events sample form has an All Sections button in the ItemsOnly view and an Items Only button in the AllSections view. If you have several views, its a good practice to inform users which view is active. Text in a layout table cell can accomplish this objective, but adding the view name to the form windows title bar shows you how to take advantage of the OnSwitchView event and the Caption property.

To program the two view buttons and the two view windows Caption properties, follow these steps.

Add event handlers for view- related operations

  1. Open the Rss2Events.sln solution in your C:Microsoft PressIntroducing InfoPath 2003Chapter16Rss2Events (Ch11)Rss2Events (Ch11) folder, if it isnt open .
  2. Choose Tools, Open InfoPath, to open the InfoPath design window, and change to the default ItemsOnly view, if necessary.
  3. Right-click the All Sections button, and choose Properties from the shortcut menu to open the Properties dialog box. Click Edit Form Code to add a btnViewAll_OnClick event-handling stub, and close the Properties dialog box.
  4. Add a Private strViewName As String = (Items Only) statement below the Private thisApplication As Application statement to create a form-level variable.
  5. Add the following statements to the btnViewAll_OnClick event handler:

    strViewName = " (All Sections)" thisXDocument.View.SwitchView("AllSections")

  6. Open the InfoPath design window, and change to the AllSections view. Right-click the Items Only button, and choose Properties from the shortcut menu to open the Properties dialog box. Click Edit Form Code to add a btnViewItems_OnClick event-handling stub.
  7. Add the following statements to the btnViewItems_OnClick event handler:

    strViewName = " (Items Only)" thisXDocument.View.SwitchView("ItemsOnly")

  8. Reopen the InfoPath design window, choose Tools, Programming, On Switch Views Event to create the OnSwitchView event handler, and add the following statements:

    With thisXDocument.View.Window 'Remove previous view name If InStr(.Caption, " (") > 0 Then .Caption = Left(.Caption, InStr(.Caption, " (") - 1) End If 'Add the new view name .Caption = .Caption + strViewName End With

  9. Press F5 to build and run the project, click the preview windows view buttons, and verify that Preview1s title bar appears as expected, except when the preview window displays the nondefault AllSections view.

Testing changes to the UI isnt complete until you verify that the changes behave as expected with multiple forms open, not just a form preview. To verify that thisXDocument.View.Window represents the currently active form, follow these steps.

Test your code with multiple open forms

  1. Close the preview window, if its open, and open the design window.
  2. Select the Fill Out A Form task pane, and click the first entry in the list to open a new form.
  3. Click both view buttons to add the view name to the form caption.
  4. Activate the designer, and repeat steps 2 and 3 for at least two more forms.
  5. Verify that all form captions contain the view name. In this case, the form opens with the default view and view name.

Programming the XDocuments Collection

Testing the Count property of the XDocuments collection lets you determine how many instances of a templates form are open , as described in Table 16-2. The following code in XDocumentsAlert.txt adds an alert, which displays information about all forms and the active form, to the btnViewItems_OnClick event handler:

With thisApplication.ActiveWindow 'Display an informative alert if more than one form is open Dim intNumXDocs As Integer = thisApplication.XDocuments.Count Dim strXDocNames As String Dim strName As String = .Caption Dim strType As String = .WindowType.ToString Dim strState As String = .WindowState.ToString Dim intCtr As Integer For intCtr = 0 To intNumXDocs - 1 'Get the open form's caption in the title bar strXDocNames += _ thisApplication.XDocuments.Item(intCtr).View.Window.Caption + ", " Next intCtr 'Trim the names string strXDocNames = Left(strXDocNames, Len(strXDocNames) - 2) If intNumXDocs > 1 Then 'Display details thisXDocument.UI.Alert("There are " + intNumXDocs.ToString + _ " XDocuments in the collection: " + strXDocNames + vbCrLf + _ "Active Window: " + strName + vbCrLf + "Window Type: " + _ strType + vbCrLf + "Window State: " + strState) End If End With

The preceding code uses the thisApplication.ActiveWindow object to point to the currently open form, but thisXDocument.View.Window and e.XDocument.View. Window work as well. All three objects are pointers to the same Window instance.

To add the code from XDocumentsAlert.txt and perform an additional test of the code you wrote in the preceding section, follow these steps.

Add an alert to display information about multiple open forms

  1. Close all open InfoPath windows , and return to Visual Studios FormCode.vb window.
  2. Open XDocumentsAlert.txt in Notepad with Word Wrap off, and copy and paste the code above the existing code in the btnViewItems_OnClick event handler.
  3. Press F5 to display a preview window, and repeat the steps in the preceding procedure, but dont close the preview window.
  4. After youve added three forms and clicked each view button at least once, the alert appears as shown here:

The alerts you add in this and later sections are intended to display information returned by the managed code you add. If you were programming these objects with JScript or VBScript, youd be using alerts primarily for debugging purposes. Relying on alerts to return suspect variable values or debugging messages makes troubleshooting complex script a cumbersome process.

Setting Custom File Paths and Names

Incorrect file locations, names, or both are the probable outcome when users must type or navigate to the path and type file names for InfoPath documents. The UI item in Table 16-3 briefly describes the SetSaveAsDialogLocation and SetSaveAsDialogFileName methods . You can hard-code the path or, for forms that arent custom-installed , specify the current template files location by making a minor modification to the XDocument.Solution.URI property value, which returns the path and file name of the forms template. Automatically generating unique file names with date/time values or from unique form field valuessuch as an order or invoice numberminimizes file-naming errors. You invoke the two SetSaveAsDialog methods from the OnLoad , OnSaveRequest , or OnSwitchViews event handlers or from any event handler that executes before users choose File, Save for a new form or File, Save As for an existing form.

Setting the Path and File Name in the OnLoad Event Handler

The following code from OnLoadSaveAsDefault.txt sets the default path to that of the forms template, which accommodates local forms and those published to a shared folder or Web server. Forms published to SharePoint sites dont require a default path, because SharePoint provides the correct path. The code creates the default file name Rss YYYYMMDDThhmm .xmlfrom a modified version of the ISO 8601 date and time when the user opens the form.

'Set default path (template folder) and file name 'Get the path from the Solution.URI property Dim strPath As String = e.XDocument.Solution.URI Dim blnIsWebSite As Boolean'Web and SharePoint sites Dim blnIsWSS As Boolean 'SharePoint site Dim blnIsFile As Boolean Dim strTestFile As String = "file:///" Dim strTestHTTP As String = "http://" Dim strTestWSS As String = "/Forms/" 'Set the flags If InStr(strPath, strTestFile) > 0 Then blnIsFile = True ElseIf InStr(strPath, strTestHTTP) > 0 Then blnIsWebSite = True If InStr(strPath, strTestWSS) > 0 Then blnIsWSS = True End If End If If blnIsFile Or blnIsWebSite Then 'Trim the URI for the path to remove the template file If blnIsWebSite Then strPath = Mid(strPath, InStr(strPath, strTestHTTP)) strPath = Left(strPath, InStrRev(strPath, "/") - 1) Else 'Remove the prefix strPath = Mid(strPath, InStr(strPath, strTestFile) + _ Len(strTestFile)) strPath = Left(strPath, InStrRev(strPath, "") - 1) 'Replace URL-encoded spaces strPath = Replace(strPath, "%20", " ") End If End If Dim datFile As DateTime = Now Dim strFile As String = datFile.ToString("s") 'Remove seconds, hyphens and colons strFile = "Rss" + Left(strFile, InStrRev(strFile, ":") - 1) + ".xml" strFile = Replace(strFile, ":", "") strFile = Replace(strFile, "-", "") 'Set the dialog variables With e.XDocument.UI If Not blnIsWSS Then 'SharePoint determines the path .SetSaveAsDialogLocation(strPath) End If .SetSaveAsDialogFileName(strFile) 'Temporary alert for testing templates published to 'Web and SharePoint sites Dim strSaveAs As String = _ "Solution.URI = '" + e.XDocument.Solution.URI + "'" + vbCrLf If blnIsWSS Then strSaveAs += "Form file = '" + strFile + "'" ElseIf blnIsWebSite Then strSaveAs += "Form server, directory, and file = '" + _ strPath + "/" + strFile + "'" Else strSaveAs += "Form path and file = '" + strPath + "" + _ strFile + "'" End If .Alert(strSaveAs) End With

To add the preceding code to the OnLoad event handler and test the code with the template on the local file system and deployed to Web and SharePoint sites, follow these steps.

Create default path and file names for a form

  1. Close all open InfoPath windows , and return to Visual Studios FormCode.vb window.
  2. Open OnLoadSaveAsDefault.txt in Notepad with Word Wrap off, and copy and paste the code above the Get All pubDates comment in the OnLoad event handler.
  3. Press F5 to build and run the code and display the alert with the original URI value and the path and file name for the preview window, similar to that shown here:

    InfoPath caches preview templates in a randomly named subfolder of My Documents shown in the alert.

  4. Close the preview window, and open the designer. Choose File, Fill Out A Form to open the Fill Out A Form dialog box, and click the Recently Used Forms link. Select the Rss2Events form, and then click the Remove This Form link to remove the form from the cache. Close the dialog box.
  5. Close the project, navigate to the ...inDebug folder, and double-click Rss2Events.xsn to open a new form, which displays an alert similar to that shown on the next page.

  6. Verify that the path and file names in the alert are correct, close the alert, and type a few characters in the Title and Description boxes. Choose File, Save to verify that the Save dialog box displays the correct path and file name. Save the form for later tests.
  7. Close the form.

This chapters On Your Own section provides exercises for publishing the completed form to Web and SharePoint sites and verifying that the form behaves as expected.

Modifying Window Properties in the OnSwitchViews Event Handler

The OnSwitchViews event fires after the OnLoad event when you open a form and each time the user changes the current view. Some Window propertiessuch as Caption arent accessible in the OnLoad event handler, and changing other Window properties can result in unpredictable exceptions. Thus, the OnSwitchViews event is the better location for initializing custom Window properties, such as the title bar text, state (normal or maximized), size , and margins. When you specify a default file name, its a good practice to replace Form# in a new forms title bar text with the proposed file name. Many forms especially those that emulate paper formsshould open with a fixed size, regardless of the users display resolution.

The following code from the OnSwitchViews.txt file replaces Form1 or higher with the default file name, specifies the normal window state, sets a fixed form width and height, and centers the form in the users display.

If (Left(.Caption, 4) = "Form" And Val(Mid(.Caption, 5, 1)) > 0) _ Or Left(.Caption, 7) = "Preview" Then 'Replace caption if Form#[#] or Preview .Caption = strFileName End If 'Force normal window state .WindowState = XdWindowState.xdWindowStateNormal 'Set fixed dimensions .Height = 380 .Width = 460 If thisApplication.UsableHeight >= .Height And _ thisApplication.UsableWidth >= .Width Then 'Center the form .Top = (thisApplication.UsableHeight - .Height) 2 .Left = (thisApplication.UsableWidth - .Width) 2 End If

To add the code from OnSwitchViews.txt and test it, follow these steps.

Add the default file name to the title bar and set the forms size

  1. Close all open InfoPath windows, and return to Visual Studios FormCode.vb window for the project.
  2. Add a Private strFileName As String declaration after the Private strViewName statement near the beginning of the code.
  3. Add a strFileName = strFile statement after the strFile = Replace(strFile, "-", "") statement in the OnLoad event handler.
  4. Comment the .Alert(strSaveAs) statement in the OnLoad event handler.
  5. Open OnSwitchViews.txt, and copy and paste the code above the Remove previous view name comment in the OnSwitchViews event handler.
  6. Press F5 to build and run the program. The preview window, after you click the Items Only button, appears similar to this:

  7. Close the preview window, and open two or more new forms to verify that the forms caption is correct. You must wait up to one minute between successive form additions to verify that the default file name differs because the last two digits of the file name are system-time seconds.

Testing the SignedDataBlocks Collection

When you digitally sign an entire form, you can select the Prompt User To Sign The Form If It Is Submitted Without A Signature check box on the Digital Signatures tab of the Form Options dialog box. There s no corresponding check box for the Enable Digital Signatures For Specific Data In The Form option. Warning the user that the form is missing or has invalid digital signatures requires iterating each member of the SignedDataBlocks collection and its Signatures collection to detect these conditions.

Listing 16-1 shows the code from the FnTestDigitalSignatures.txt file for the TestDigitalSignatures function, which you can call from the OnSaveRequest or OnSubmitRequest event handler. If a user receives a warning message box and clicks Yes, the thisXDocument.UI.ShowSignatureDialog() statement opens the Digital Signatures dialog box so that the user can correct the problem.

Listing 16-1: The TestDigitalSignatures function.

Private Function TestDigitalSignatures() As Boolean 'Iterate SignedDataBlocks members and test for 'presence and validity of signatures Dim strConfirm As String With thisXDocument.SignedDataBlocks If .Count > 0 Then strConfirm = "This document has " + _ .Count.ToString + " digitally signed data block(s)." + vbCrLf Dim intBlock As Integer Dim intSig As Integer Dim intMissing As Integer Dim intBadSigs As Integer Dim strSigners As String For intBlock = 0 To .Count - 1 strSigners = "" 'Iterate the blocks With .Item(intBlock) 'Add the signature name strConfirm += "Block " + (intBlock + 1).ToString + _ " (" + .Name + ") has " + .Signatures.Count.ToString + _ " signature(s)." + vbCrLf 'Add the signature relationship strConfirm += "The signature relationship is '" Select Case .SignatureRelation Case XdSignatureRelation.xdSignatureRelationSingle strConfirm += "Single" Case XdSignatureRelation.xdSignatureRelationCoSign strConfirm += "Co-sign" Case XdSignatureRelation.xdSignatureRelationCounterSign strConfirm += "Counter-sign" End Select strConfirm += "'." + vbCrLf If .Signatures.Count > 0 Then For intSig = 0 To .Signatures.Count - 1 'Iterate the signatures and add the signer 'and certificate issuer Dim strIssuedTo As String = _ .Signatures.Item(intSig).Certificate.IssuedTo strConfirm += " Signature " + (intSig + 1).ToString + _ " is issued to " + strIssuedTo + _ " and issued by " + _ .Signatures.Item(intSig).Certificate.IssuedBy If .Signatures.Item(intSig).Status = _ XdSignatureStatus.xdSignatureStatusValid And _ InStr(strSigners, strIssuedTo) = 0 Then strConfirm += " (Valid)" Else strConfirm += " (Invalid)" intBadSigs += 1 End If strSigners += .Signatures.Item(intSig).Certificate.IssuedTo strConfirm += vbCrLf Next intSig Else intMissing += 1 End If End With Next intBlock If intMissing > 0 Or intBadSigs > 0 Then 'Construct the confirm dialog string If intMissing > 0 Then strConfirm += intMissing.ToString + _ " signature(s) are missing" If intBadSigs > 0 Then strConfirm += " and " + intMissing.ToString + _ " signature(s) are invalid." + vbCrLf strConfirm += "Do you want to sign or fix this document?" Else strConfirm += "." + vbCrLf + _ "Do you want to sign this document?" + vbCrLf + _ "(Disregard co- or counter-signatures that don't apply " + _ "at this point)" End If Else If intBadSigs > 0 Then strConfirm += vbCrLf + intBadSigs.ToString + _ " signature(s) are invalid." + vbCrLf + _ "Do you want to fix this document?" End If End If 'Handle response from confirm dialog Dim xdConfirm As XdConfirmChoice = _ thisXDocument.UI.Confirm(strConfirm, _ XdConfirmButtons.xdYesNoCancel) Select Case xdConfirm Case XdConfirmChoice.xdYes 'Show the signature dialog thisXDocument.UI.ShowSignatureDialog() Return True Case XdConfirmChoice.xdCancel 'Cancel save if called in OnSaveRequest handler Return False Case XdConfirmChoice.xdNo 'Not a wise move Return True End Select

The Rss2Events project in your ...Rss2Events (Ch11)Rss2Events (Ch11) subfolder contains two predefined SignedDataBlocks ”ChannelPlusItems and Items ” that don t have digital signatures. To add the TestDigitalSignatures function to your code and test its execution, follow these steps.

Add the test function and call it from the OnSaveRequest event handler

  1. Close all open InfoPath windows , and return to Visual Studio s FormCode.vb window.
  2. Open FnTestDigitalSignatures.txt in Notepad with Word Wrap off, and copy and paste the immediately above the End Class statement near the end of the code.
  3. Choose Tools, Display InfoPath to open the InfoPath design window. Choose Tools, Form Options in the InfoPath design window to open the Form Options dialog, and click the Open And Save tab. Select the Save Using Custom Code check box, click the Edit button to add an OnSaveRequest event-handling stub, close the dialog, and return to the FormCode.vb window.
  4. Replace the event handler s stub code with the following:

    'Test digital signatures before saving form If TestDigitalSignatures() Then e.IsCancelled = e.PerformSaveOperation Else e.IsCancelled = True End If e.ReturnStatus = True

  5. Press F5 to build and run the code, close the preview, and open a new form. Type a few characters in the preview window s Title and Description text boxes, and press Ctrl+S or choose File, Save to display the confirm message box, shown here:

  6. Click Yes to open the Digital Signatures dialog box, add one or more signatures to the ChannelPlusItems block, and click Close.
  7. Press Ctrl+S again to provide details of the digital signature you added in the message box, which looks similar to this:

  8. Click Yes, and add a signature to the Items block. Click Close, and press Ctrl+S to verify that the message box no longer appears.

If you add the same digital signature more than once to a field that requires a co-signature or counter-signature, the confirm message box states that the co-signature or counter-signature is invalid.

Summary

InfoPaths COM object hierarchy, which you access through the InfoPath PIA, is much simpler than that of other Office applications. Most InfoPath projects involve getting or setting properties and invoking methods of the Application and XDocument objects and their descendants with event-handling code.

The Application object has a set of properties to test for a live network connection and access to file servers and Web sites. The Application. User interface has methods to determine whether the forms user name matches a specified logon name and is a member of a particular local or domain-level security group . The XDocument objectss Role property returns the name of the current users role.

The XDocuments collections XDocument members and their child objects are the primary targets of event-handling code. The XDocuments.Count property returns the number of currently open forms; each form has its own XDocument instance. The thisXDocument variable and e.XDocument event argument return the instance of the form with the focus.

This chapters procedures showed you how to use button controls to change form views; how to add the view name to the forms caption; and how to set default path and file names for saving forms to the local file system, shared folders, Web sites, and Windows SharePoint Services sites. You also learned how to display the default file name in the forms title bar and test individually signed sections or fields for the presence and validity of digital signatures.

Q A

1.  

Can I access InfoPath form controls and their properties with managed code?

2.  

Can I import VBA or script code to an InfoPath project s FormCode.vb or FormCode.cs window?

3.  

Setting Option Strict On generates a large number of errors when building code that runs fine with Option Strict Off . Is it worth the effort to fix the type conversion errors?

4.  

Why do I get a Security error message when I attempt to execute a member of a .NET class that I added to the project?

Answers

1.  

No. Visual Studio Windows and Web forms projects provide full programmability of controls, but InfoPath doesn t expose controls, which are defined in ViewName .xsl files, to .NET or script code.

2.  

Yes, with reservations . Most InfoPath VBScript files can be built and run with Option Strict Off , and general-purpose Visual Basic 6 and VBA procedures or functions will compile without major modifications. Importing InfoPath JScript files to FormCode.cs requires substantial rewriting, because C# doesn t offer the equivalent of Option Strict Off . InfoPath doesn t support Microsoft Visual J# code.

3.  

Yes. You should set Option Strict On for all Visual Basic .NET projects, except when initially testing Visual Basic 6 projects you convert with the Upgrade Wizard, VBA code you import into the Convert Visual Basic 6 Code dialog box, or VBScript you paste into the FormCode.vb window. Option Strict Off enables implicit late binding of Object variables . Late binding requires helper objects and reflection to invoke the correct methods when your project runs, and it uses Variant -style type coercion to accommodate type conflicts. Early binding eliminates this overhead, enables IntelliSense for strongly typed variables, and disables what many Visual Basic developers call Evil Type Coercion, or ETC. Strong typing is especially important for projects that use custom code for database- related operations. To learn more about this subject, search the Visual Studio Help index for Visual Basic .NET, implicit late binding .

4.  

Forms must be fully trusted to execute members of .NET classes that aren t digitally signed by Microsoft or by the European Computer Manufacturers Association (ECMA, the standards body for ECMAScript ”formerly JavaScript ”and the C# language). Some Microsoft .NET namespaces ”such as Microsoft. mshtml ” require fully trusted forms. You can t sign a form with a code signing certificate while you re debugging it; you must sign the template s .xsn file and test it. An alternative is to specify that all InfoPath managed code runs with full trust on your computer; Chapter 17 shows you how to change the .NET Framework 1.1 s security level.

On Your Own

Here are some additional exercises to validate the Visual Basic .NET code you added in this chapter:

  1. Publish your form with all procedures completed (or the final version of Rss2Events in your ...Rss2EventsFinalRss2EventsFinal subfolder) to a Web site, using the techniques described in the section Publishing Templates to an Intranet Site, in Chapter 12. Create multiple forms, and verify that you can save them to the Web server.
  2. If you have access to a Windows SharePoint Services site, publish the same form to a library by following the instructions in the section Publishing Templates to SharePoint Form Libraries, in Chapter 12. Verify that multiple forms, which dont have default path values in this case, behave as expected under SharePoint management.
  3. Test submission of the form to the SharePoint site you created in the preceding exercise. See the section Submitting Documents to a SharePoint Forms Library, in Chapter 12, for instructions.

Категории