Add an event handler using the InfoPath object model

The menu commands for adding event handler functions in a form template project that is compatible with the InfoPath 2003 object model are essentially the same as those for other types of form templates. For example, in order to add an OnLoad event handler, with the form template open in the InfoPath designer, click the On Load Event command on the Developer tab. The focus automatically switches to the form code for the OnLoad event handler in the Visual Studio 2012 code editor.

In managed-code form template projects compatible with InfoPath 2003, the class that contains event handler functions and the event handlers themselves are identified by attributes specific to InfoPath in the code module.

Adding event handlers

All of the following procedures assume that you have a form template project open in Microsoft InfoPath with Visual Studio 2012.

Add an event handler for the OnClick event of a command button

  1. In the Controls pane, click Button to add a button to the form.

  2. On the Properties tab, click Custom Code.

    The focus switches to the stub for the event handler for the OnClick event in the code editor.

Add an event handler for the OnBeforeChange, OnValidate, or OnAfterChange event of a field or group

  1. Right-click a data-entry control bound to the field or group, such as a Text Box control.

  2. Point to Programming, and then click one of the commands, such as On Validate Event.

    The focus switches to the stub for the event handler for one of the following events in the code editor: OnBeforeChange, OnValidate, or OnAfterChange.

Add an event handler for the OnLoad, OnSwitchView, OnContextChange, or OnSign event of a form

  • On the Tools menu, point to Programming, and then click the form event that you want to write an event handler for.

    The focus switches to the stub for the event handler for one of the following in the code editor: OnLoad, OnSwitchView, OnContextChange, or OnSign.

Add an event handler for the OnSubmitRequest event of a form

  1. On the Data tab, click Submit Options.

  2. Select the Allow users to submit this form check box, and then click Perform custom action using Code.

  3. Click Edit Code, and then click OK.

    The focus switches to the stub for the event handler for the OnSubmitRequest event in the code editor.

Add an event handler for the OnSaveRequest event of a form

  1. Click the File tab, and then click Form Options.

  2. In the Save category, click Save using custom code, click Edit, and then click OK.

    The focus switches to the stub for the event handler for the OnSaveRequest event in the code editor.

Add an event handler for the OnVersionUpgrade event of a form

  1. Click the File tab, and then click Form Options.

  2. In the Versioning category, select Use custom event from the Update existing forms list, click Edit, and then click OK.

    The focus switches to the stub for the event handler for the OnVersionUpgrade event in the code editor.

Add an event handler for the OnMergeRequest event of a form

  1. Click the File tab, and then click Form Options.

  2. In the Advanced category, select the Enable Form merging and the Merge using custom code check boxes, click Edit, and then click OK.

    The focus switches to the stub for the event handler for the OnMergeRequest event in the code editor.

Adding an event handler for the OnAfterImport event

To add event handlers for the OnAfterImport event, you must open the form code for your managed-code form template and add the event handler function manually. For information on how to write an event handler for this event, click the link for the OnAfterImport event.

Adding an event handler for a secondary data source

The following example shows how to add an event handler for a secondary data source. The example assumes a secondary data source from a resource file named books.xml, which has the following schema:

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="https://www.w3.org/2001/XMLSchema">
    <xsd:element name="catalog">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="book" minOccurs="0" maxOccurs="unbounded"></xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="genre" type="xsd:string"></xsd:element>
    <xsd:element name="author" type="xsd:string"></xsd:element>
    <xsd:element name="book">
        <xsd:complexType>
            <xsd:all>
                <xsd:element ref="author" minOccurs="0" maxOccurs="1"></xsd:element>
                <xsd:element ref="title" minOccurs="0" maxOccurs="1"></xsd:element>
                <xsd:element ref="genre" minOccurs="0" maxOccurs="1"></xsd:element>
                <xsd:element ref="price" minOccurs="0" maxOccurs="1"></xsd:element>
                <xsd:element ref="publish_date" minOccurs="0" maxOccurs="1"></xsd:element>
                <xsd:element ref="description" minOccurs="0" maxOccurs="1"></xsd:element>
            </xsd:all>
            <xsd:attribute ref="id"></xsd:attribute>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="price" type="xsd:string"></xsd:element>
    <xsd:element name="title" type="xsd:string"></xsd:element>
    <xsd:element name="publish_date" type="xsd:string"></xsd:element>
    <xsd:element name="description" type="xsd:string"></xsd:element>
    <xsd:attribute name="id" type="xsd:string"></xsd:attribute>
</xsd:schema>

The form's view is built from this data source. The form code creates a hash table based on the authors and the number of books they have written. You can update an entry from the table shown in the view and the OnAfterChange event handler updates the hash table. Note that the DataObject property of the InfoPathEventHandler attribute (which is implemented by the InfoPathEventHandlerAttribute class) is used to reference the secondary data source.

namespace AuxDom
{
    // InfoPathNamespace attribute goes here.
    public class AuxDom
    {
        private XDocument thisXDocument;
        private Application thisApplication;
        private Hashtable authors;
        public void _Startup(Application app, XDocument doc)
        {
            thisXDocument = doc;
            thisApplication = app;
            authors = new Hashtable();
        }
        public void _Shutdown()
        {
            authors.Clear();
        }
        // The following function handler is created by Microsoft
        // Office InfoPath. Do not modify the type or number of
        // arguments. 
        [InfoPathEventHandler(EventType=InfoPathEventType.OnLoad)]
        public void OnLoad(DocReturnEvent e)
        {
            IXMLDOMDocument books = thisXDocument.GetDOM("books");
            DOMNodeList externalAuthors = books.selectNodes("/catalog/book/author");
            foreach (IXMLDOMNode authorNode in externalAuthors)
            {
                AddBookFromAuthor(authorNode.text);
            }
        }
        // The following function handler is created by Microsoft
        // Office InfoPath. Do not modify the type or number of
        // arguments. 
        [InfoPathEventHandler(MatchPath="/catalog/book/author", EventType=InfoPathEventType.OnAfterChange, DataObject="books")]
        public void books__author_OnAfterChange(DataDOMEvent e)
        {
            if (e.IsUndoRedo)
            {
                // An undo or redo operation has occurred and the DOM 
                // is read-only.
                return;
            }
            
            if (e.Source.text != e.NewValue.ToString())
            {
                RemoveBookFromAuthor(e.OldValue.ToString());
                AddBookFromAuthor(e.NewValue.ToString());
            }
        }
        private void AddBookFromAuthor(string authorName)
        {
            if (authors.Contains(authorName))
            {
                authors[authorName] = (int)authors[authorName] + 1;
            }
            else
            {
                authors.Add(authorName, 1);
            }
        }
        private void RemoveBookFromAuthor(string authorName)
        {
            if (authors.Contains(authorName))
            {
                authors[authorName] = (int)authors[authorName] - 1;
            }
            if ((int)authors[authorName] == 0)
            {
                authors.Remove(authorName);
            }
        }
        // The following function handler is created by Microsoft
        // Office InfoPath. Do not modify the type or number of
        // arguments. 
        [InfoPathEventHandler(MatchPath="ShowAuthors", EventType=InfoPathEventType.OnClick)]
        public void ShowAuthors_OnClick(DocActionEvent e)
        {
            // Write your code here.
            StringBuilder report = new StringBuilder();
            foreach (string authorName in authors.Keys)
            {
                report.Append(authorName + ",\t\t\t");
                report.Append(authors[authorName] + "\n");
            }
            thisXDocument.UI.Alert(report.ToString());
        }
    }
}

How the class that contains event handlers is identified

When you create a new InfoPath form template project that is compatible with the InfoPath 2003 managed code object model, an assembly-level System.ComponentModel.Description attribute is applied to the class at the beginning of the form code module to identify the class that contains all event handlers for the form template.

Important

Do not modify the System.ComponentModel.Description attribute in this class. If you do so, your form template will not be able to identify where event handlers are located, and the event handlers will fail to run.

using System;
using Microsoft.Office.Interop.InfoPath.SemiTrust;
// Office integration attribute. Identifies the startup class for the // form. Do not modify.
[assembly: System.ComponentModel.DescriptionAttribute(    "InfoPathStartupClass, Version=1.0, Class=Template1.FormCode")]
Imports System
Imports Microsoft.Office.Interop.InfoPath.SemiTrust
' Office integration attribute. Identifies the startup class for the form. Do not modify.
<Assembly: System.ComponentModel.DescriptionAttribute( _    "InfoPathStartupClass, Version=1.0, Class=Template1.FormCode")>

How event handlers are identified

When you add a new event handler using menu commands or buttons in the InfoPath design mode user interface, the stub for the event handler function is written into the form. The following example shows the stub event handler created for an OnValidate added for a field named 'total'.

[InfoPathEventHandler(MatchPath="/invoice/total", EventType=InfoPathEventType.OnValidate)]
public void total_OnValidate(DataDOMEvent e)
{
    // Write your code here.
}

<InfoPathEventHandler(MatchPath:="/invoice/total",EventType:= OnValidate)> Public Sub total_OnValidate(ByVal e As EventArgs)
    ' Write your code here.
End Sub

You can then add code that invokes members of the InfoPath object model using the private cached members of the thisXDocument or thisApplication variables, or by using the members accessed from the e EventArgs object received by the event handler:

thisXDocument.UI.Alert.(e.Site.text);

thisXDocument.UI.Alert.(e.Site.text)

The InfoPathEventHandler attribute (as defined by the InfoPathEventHandlerAttribute class) is the custom attribute for functions that will be used as event handlers.

When required by the event, the MatchPath parameter (as defined by the MatchPath property of the InfoPathEventHandlerAttribute class) specifies an XPath expression that identifies the event source. The EventType parameter (as defined by the EventType property of the InfoPathEventHandlerAttribute class) specifies the type of event. You should not change the values of these parameters. If the values of these parameters are changed, the event handler may not compile correctly, or event notification will not occur as expected.

Obfuscating code in event handlers

If you run an obfuscator utility on the assembly that is generated when a managed-code form template is compiled ( projectname.dll), InfoPath will not be able to load the assembly when a user opens the form. If you want to obfuscate the code for your event handlers or other form code, you must put the code that you want to obfuscate in a separate assembly, and reference that assembly in your project, and then call members of the referenced assembly from FormCode.cs or FormCode.vb. It is important that you run the obfuscator utility only on the referenced assembly.

See also