Programming InfoPath

InfoPath uses a declarative, per-form, event-driven approach to programming customized forms. That is, code consists of declarations that define which event handlers are to be invoked when form elements or data elements source events. Code in InfoPath is always written behind a specific form template; it is not possible to write "application-level" code that is executed for all form templates. Code runs when events are raised that have been declaratively handled by event handlers.

There are two "root" objects in the InfoPath object model. The Application object is the root of the runtime object model; every programmable object in InfoPath can be accessed through the Application object. The other "root" object is the ExternalApplication object. The ExternalApplication object is useful for automating InfoPath by an automation executable rather than from code behind a form, as shown in Listing 12-1. However, this chapter only discusses how to create code behind a form and does not cover automation executables further.

When you create an InfoPath form template project in VSTO, Visual Studio automatically generates a FormCode.cs file for you to add the code behind the form. It generates some "boilerplate" code for you to get started containing methods called when the InfoPath form starts up and shuts down, as shown in Listing 12-2.

Listing 12-2. The FormCode.cs File

namespace PurchaseOrder { //[Attribute omitted] public class PurchaseOrder { private XDocument thisXDocument; private Application thisApplication; public void _Startup(Application app, XDocument doc) { thisXDocument = doc; thisApplication = app; } public void _Shutdown() { } } }

When the InfoPath form starts up, InfoPath calls the _Startup method and passes in an Application and XDocument object. By default, the managed class that represents the InfoPath form stashes away references to these objects in thisApplication and thisXDocument so that your event handlers and other code can use them later. The same Application object is passed to all currently executing forms. The XDocument object is a specific instance that refers to the form to which it is passed.

Although you now have references to the Application and XDocument objects in the _Startup method, do not actually make any InfoPath object model calls yet. Calling the InfoPath object model is not allowed in either the _Startup or _Shutdown methods. During these method, calls to the object model are unavailable because the form is either still in the process of being created or is being terminated.

 

Event-Based Programming

While filling out the form, various user actions directly or indirectly trigger events. Take the OnLoad event, for example. To handle (that is, register an event handler to be called when the event occurs) the OnLoad event, select the InfoPath designer's Tools menu, then the Programming submenu, and then the On Load Event menu item. Notice that the InfoPath designer automatically creates a code stub and handles the event. Whenever you add an event handler to an InfoPath form, you always do it using the InfoPath designer window and its associated menus, never by using any commands within Visual Studio.

[InfoPathEventHandler(EventType=InfoPathEventType.OnLoad)] public void OnLoad(DocReturnEvent e) { // Write your code here }

You will immediately notice that an InfoPath event is not hooked up in the traditional .NET way of creating a new delegate and adding that delegate to an object that raises the event using the += operator. Instead, InfoPath events are hooked up via attributesthe InfoPath runtime reflects on the attributing of methods in your code to determine events that are handled by your code and the methods to call when an event is raised. In this case, the attribute InfoPathEventHandler is added to your OnLoad event handler. This attribute is constructed with EventType=InfoPathEventType.OnLoad, which tells the InfoPath runtime to raise the OnLoad event on this attributed method.

Let's add some code to our OnLoad handler to restrict users from creating a new form if it is not presently business hours. (Note that this does not restrict editing existing forms, just creating new ones.) Listing 12-3 shows the new OnLoad handler.

Listing 12-3. On OnLoad Handler That Restricts Creation of New Forms to Be During Business Hours

[InfoPathEventHandler(EventType=InfoPathEventType.OnLoad)] public void OnLoad(DocReturnEvent e) { if ((DateTime.Now.Hour < 8 // earlier than 8am || DateTime.Now.Hour > 17 // later than 5pm || DateTime.Today.DayOfWeek == DayOfWeek.Saturday || DateTime.Today.DayOfWeek == DayOfWeek.Sunday) && thisXDocument.IsNew) // is a new form { thisXDocument.UI.Alert("You can only create a new" + " mortgage application 8am to 5pm, Monday through Friday."); e.ReturnStatus = false; // fail loading the form } }

The IsNew property and UI.Alert method both require the domain security level.

All form events in InfoPath are cancelable through code. In this OnLoad event example, setting the ReturnStatus property to false on the DocReturnEvent object e tells InfoPath to fail the OnLoad event (and thus fail loading the form) when the event handler has returned. The default value is true.

Previewing

Press F5 or choose Start from the Debug menu in Visual Studio and the code in Listing 12-3 will be compiled and start running in InfoPath's preview form mode. Depending on what time and day you run the code in Listing 12-3, you may or may not be able to fill out the form!

Suppose you are working latelater than 5 p.m. at least. The OnLoad handler will not allow you to create a new form because thisXDocument.IsNew always returns true when you press F5 or choose Start from the debug menu. How can you force the form to look like an already created form? If you double-click the template.xml file (located in the Visual Studio project folder), you will start InfoPath and cause InfoPath to think it is opening an already created form. The template.xml file is used internally by InfoPath when creating a new form after you double-click the .XSN form template. However, directly opening this file tricks InfoPath into thinking it is an existing or previously saved form.

Previewing is a very useful technique when designing and debugging a form, but it is important to realize that previewing a form causes the following side effects:

So in addition to previewing, you should also use your form in a production environment with InfoPath running by itself to verify that everything works properly.

Категории