Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

  • Microsoft InfoPath 2010

    Welcome to the InfoPath Team Blog


    Welcome to the InfoPath team blog here at

    The InfoPath Team is looking forward to posting a variety of topics for our InfoPath users, including:

    • Feature highlights.
    • Code snippets.
    • Our best practices.
    • Tips 'n Tricks.
    • Common work-arounds.
    • Show how to leverage other Microsoft technology with InfoPath.  

    We're super-excited about InfoPath and look forward to helping our customers realize the most they can out of our new Office System 2003 application.

    Please leave some feedback if there are areas you'd like to see us cover (and please remember the community support via the microsoft.public.infopath newsgroup!).

  • Microsoft InfoPath 2010

    Enabling Cuneiform Support in InfoPath 2003 SP1


    Very often customers ask how they can enable Cuneiform entry in forms being deployed to their overseas customers. One of the exciting additions in the upcoming service pack is Antediluvian Syllabary support. With this feature, users will be able enter Cuneiform text naturally into the editor via an IME. InfoPath's Cuneiform support includes polyvalent logograms as well as transliteration.

    To enable this feature, you must first apply a language pack. To do this, go to Start -> All Programs -> Microsoft Office -> Microsoft Office Tools -> Microsoft Office 2003 Language Settings

    In the list of Available Languages, select "Akkadian"

    Click Add >> and then Click OK. You will need to restart InfoPath.

    This will also install all the files needed for the Voynich, Vinca, Iberic, Etruscan, Linear A (Minoan form), Linear B (Greek form), and Rongo Rongo language support. Please be aware that the default currency will be switched to zuzu and the default date format will be synodic.

    Cuneiform support is especially powerful when combined with Microsoft's Tablet platform.

    The InfoPath Team wishes you a happy April Fool's Day!

    (Picture of the InfoPath editor in Akkadian)

  • Microsoft InfoPath 2010

    Advanced server-side authentication for data connections, part 3

    This is the final segment of my three part series. In the first part of this series I introduced the concepts involved in three tier authentication. Then I covered single sign-on with some code. Now we'll go one step further…
    Authorization using the Web service proxy
    InfoPath Forms Services includes a Web service proxy which can forward SOAP requests to a Web service to enable authorization for a data query.  The premise is simple – the proxy runs under an account that is trusted by the Web service.   The Web service authenticates the trusted account.  In addition, the proxy sends the identity of the calling user in the SOAP header using a WS-Security UsernameToken.  The Web service can then use the provided identity to determine what data to return from the query.
    Setting up a connection to use the proxy is straightforward.  First of all, the connection has to use settings from a UDC file on the server.   The UseFormsServiceProxy attribute on the ServiceUrl element in the UDC file determines whether InfoPath and Forms Services will forward the Web service request using the proxy:
    <udc:ServiceUrl UseFormsServiceProxy="true">
    Everything else on this end is automatic.  It's a little more interesting on the Web service end.

    It's tempting to consider using the WSE 2.0 library to consume the UsernameToken from the Web service request.  WSE 2.0 has methods to automatically consume WS-Security headers.  However, the default behavior of WSE 2.0 is to attempt to logon using the credentials in the UsernameToken.  It is possible to override the default behavior by specifying an alternate UsernameTokenHandler.  However, there is a more straightforward approach.
    First, declare an array of SoapUnknownHeader at class scope in your service:
    public SoapUnknownHeader[] unknownHeaders;
    Then declare a SoapHeader attribute for the web method:
    public ExpenseInfo[] GetMyExpenses()
    In your web method, look for the UserName element in the header array, which is returned as an XML Document.
    if (null != unknownHeaders && unknownHeaders.Length > 0)
         // look for a userNameToken and return the username if present
              strUserName = unknownHeaders[0].Element.CreateNavigator().SelectSingleNode("//*[local-name(.)='Username']").Value;
         catch (Exception)
    In the example, I'm searching for a Username element anywhere in the headers.  To be more precise, the UserName is within a UsernameToken element, which is in turn under a Security header in the WS-Security namespace.  The entire SOAP header sent by the proxy looks like this:
    I've put the code to get the username within a utility function called GetUserName.  In the function, I look first for the usernametoken.  If this is not present, I get the current Windows user.  In either case, I strip off the domain portion of the identifier and return the unadorned username.
    private string GetUserName(SoapUnknownHeader[] unknownHeaders)
      bool fUserFound = false;
      string strUserName = string.Empty;
      if (null != unknownHeaders && unknownHeaders.Length > 0)
      // look for a userNameToken and return the username if present
          strUserName = unknownHeaders[0].Element.CreateNavigator().SelectSingleNode("//*[local-name(.)='Username']").Value;
        catch (Exception)
        if (string.Empty != strUserName)
          fUserFound = true;
      if (!fUserFound)
        // return the current Windows identity
        strUserName = WindowsIdentity.GetCurrent().Name;
      // trim off the domain string if present
      int nDomainStringIndex = strUserName.IndexOf('\\');
      if (nDomainStringIndex > 0)
        strUserName = strUserName.Substring(nDomainStringIndex + 1);
      return strUserName;
    In order to use the identity to retrieve data, I use it as part of the query against my database.  Here's the entire Webmethod. The code assumes that you have an Expense database with a table called Expenses, and that one column of the table, called Employee, contains the Windows username of the employee who filed the expense.
    public ExpenseInfo[] GetMyExpenses()
      ExpenseInfo[] oReturn = null;
      DataSet oDS = new DataSet();
      string strQuery = string.Format("SELECT ExpenseID, Description, Date, Amount FROM Expenses WHERE Employee = '{0}'", GetUserName(unknownHeaders));
        m_Adapter = new SqlDataAdapter(strQuery, m_Connection);
        m_Adapter.Fill(oDS, "Expenses");
        int cRows = oDS.Tables["Expenses"].Rows.Count;
        oReturn = new ExpenseInfo[cRows];
        for (int nRowIterator = 0; nRowIterator < cRows; nRowIterator++)
          oRow = oDS.Tables["Expenses"].Rows[nRowIterator];
          oReturn[nRowIterator] = new ExpenseInfo();
          oReturn[nRowIterator].Amount = oRow["Amount"].ToString();
          oReturn[nRowIterator].ExpenseID = oRow["ExpenseID"].ToString();
          oReturn[nRowIterator].Date = oRow["Date"].ToString();
          oReturn[nRowIterator].Description = oRow["Description"].ToString();
      catch (Exception ex)
      if (m_Connection.State != ConnectionState.Closed)
      return oReturn;
    - Nick
    Program Manager
  • Microsoft InfoPath 2010

    Cool Form! MS Store Inventory Checklist


    This week's cool form is an inventory check list form that is used in the Microsoft Company Store. The form contains 2 views.

    The 1st view contains a set of checks that need to be completed by store employees.

    The 2nd view displays the list of checks that have not yet been completed by the user.


    If you have a “cool” form that you would like to share with us, please send an e-mail with the following details to -

    • Attach 1 or 2 screenshots of your form
    • Provide a brief description of the form
    • You may also attach the XSN file (optional)

    The most popular submissions will be featured on our blog in future posts.

    Check out other Cool Forms here.

  • Microsoft InfoPath 2010

    Introducing Horizontal Repeating Tables

    InfoPath 2007 adds horizontal repeating table to the control toolbox for when you want data to be entered or displayed in a structured, tabular format, and when you want users to be able to add additional columns instead of rows.
    For example, you might use a horizontal repeating table to collect sales data for each quarter:
    Making it wrap
    When designing your form template, horizontal repeating table looks like a composite control -- it’s made from a horizontal repeating section and layout tables (I'll cover horizontal repeating section in my next post). Horizontal repeating table can be configured to wrap or scroll. By default, it will wrap to the next line, to provide a better printing experience.
    You can change the behavior of the control by resizing the layout tables; for example, to change the wrapping point, resize the rightmost border of the layout table:
    This will allow only two instances of the repeating column to fit on one line; the next two will go to the next line, and so forth:
    Making it scroll
    You may want to set an upper bound on the amount of real estate that a horizontal repeating table can take up; in that case, you need to make the control scroll. User experience will then be similar to the following:
    To achieve such behavior, you need to make the following modifications to your form template:
    1. Encapsulate the repeating section component of the horizontal repeating table in a scrolling region.
    2. Set the properties on the scrolling region:
      • Show horizontal scroll bars: always
      • Show vertical scroll bars: never
      • Wrap text: unset
      • Margins: all zero
      • Padding: all zero
      • Size: appropriate height and width
      • Borders: no borders
    3. Resize the rightmost border of the layout table that contains the horizontal repeating table to match the border of the scrolling region.
    When you’re done, your form template will look similar to the following in Design mode:
    Scrolling is often desirable for electronic forms, but is not ideal for printing. If you want to achieve both, you need to use scrolling in the view that users will see when filling out the form and wrapping in an associated printable view.
    Data binding of a horizontal repeating table is identical to that of a regular repeating table or section.  Horizontal repeating tables support conditional formatting, data validation, rules, calculations, other InfoPath data features that a regular repeating tables support.
    Note that horizontal repeating tables are only supported in InfoPath 2007 client.
    - Alex Weinstein
    Program Manager
  • Microsoft InfoPath 2010

    Publish faster to even more places with InfoPath 2007

    When designing a form template, publish is an important step to make the form available for end users of the form. In InfoPath 2007, we have made some modifications and improvements to the publish process. This article is intended to highlight some of the key changes you will encounter in the publishing wizard.
    Let us start off with a snapshot of the page in the wizard which helps you decide where to publish.
    Here is the second page in the wizard when you invoke File/Publish in InfoPath 2003.
    Here is the first page in the wizard when you invoke File/Publish in InfoPath 2007.
    Here are some key differences that you can notice:
    • Windows SharePoint Services server is now the default option and it can be used to publish to SharePoint server with or without InfoPath Forms Services. This option itself has several new features worth a blog post of its own.
    • Shared folder and web server options have been collapsed into one, namely, network location. This option includes the functionality of both shared folder and web server.
    • Email has been added to allow sharing templates via email. This functionality used to be available previously under File menu as "Send form as attachment". This option can be used to generate InfoPath email forms integrated with Outlook 2007.
    • Installable form template option has been added. This makes it really easy to create installable solutions which you may need to do if you are form's security setting is fully trusted.
    • A new branch to publish a Document Information Panel template on a SharePoint site has been added. However this option will show up only when it is relevant (i.e. you are customizing a content type in SharePoint).
    Work on it here, publish it there
    Another important difference is the concept of "working/developer copy" vs. "published copy". In InfoPath 2003, when you complete the publish wizard, your working solution will be the same as the published copy. In other words, any changes you are making from then on is on the published copy which may not be something you want to do. In InfoPath 2007, when you complete the publish wizard, your working solution is still the original copy that you were working with and subsequent changes to the solution will not affect the published copy unless you chose to publish those additional changes.
    Publish once, publish again
    We have also made it really easy to make updates to your published copy. Once you have successfully published once, the next time you go through the wizard, it will remember your previous information and automatically populate them for you. This makes it really easy to go through the wizard for subsequent publishing without having to re-enter various information.
    Hope you have a great experience publishing form templates using InfoPath 2007.
    Senior Development Lead
  • Microsoft InfoPath 2010

    Dynamic Pictures

    When designing a feature-rich InfoPath form template, it is sometimes necessary to provide a dynamic image in response to user action. InfoPath picture control hides treasures that will help you satisfy such a requirement. In this article, we will explore a technique that allows you to make this happen without writing any code.
    Here is our scenario: build a hardware order form for the telecommunications department. In the form, we would like to let the user choose the phone that they want to order, and show them a picture of the phone as soon as they select it.
    The following steps will make this possible:
    1. Place pictures of available phones in a shared location; let's call it http://mysite/phones/photos/. Pictures are named according to phone ID's - for example, 1.jpg, 2.jpg, 3.jpg, etc.

    2. Insert a picture control. When you do so, InfoPath will ask whether you want the picture to be included into the form, or if you want it to be linked. Choose the second option.
    3. Take a look at the node that was just inserted into your data source by going to View | Data Source. Let’s call the new node hyperlinkDataSource; it’s a node with data type "hyperlink".

    4. Insert a text box that’s also bound to hyperlinkDataSource.

    5. Preview the form. Use the picture control to attach the image. Observe how the path in the text box changes to reflect the path of the image you just attached. Try changing the value of the text box to point to a different picture. Note how the picture control displays the new picture when you tab out of the text box.

      Now, we want this step to happen programmatically, when the user selects the phone from the dropdown of available phones.

    6. Create a phone picker dropdown; labels in the dropdown will show phone names, and values will contain phone ID's that correspond to file names we used in step 1. The simplest way to do this is to enter the items manually; don't forget to include the default "pick a phone" item.

    If you want to get fancy, you can use a secondary data source - web service - to provide the list of available phones.

    1. Create a rule on the phonePicker node: set the value of hyperlinkDataSource to

      concat("http://mysites/phones/photos/", phonePicker, ".jpg")

    2. Go to control properties for the new picture control; uncheck the “Allow users to browse for new pictures” property.

    We're done! Preview the form and try selecting a few phones from the dropdown.
    Picture control is available in both InfoPath 2003 and 2007, however it is not supported in browser-enabled form templates.
    Alex Weinstein
    Program Manager
  • Microsoft InfoPath 2010

    Microsoft Office InfoPath 2003 Technical FAQ and the InfoPath Viewer


    Looking for some of our answers to questions we get a lot?  Pull up the Microsoft Office InfoPath 2003 Technical FAQ - if you don't find the answer you need in the FAQ, please ask your question on the newsgroup microsoft.public.infopath where MVPs, experienced InfoPath users, and Microsoft InfoPath team members can all help.

    One question that comes up often regards a no-cost InfoPath Viewer.  Here are three Q&A's in the FAQ worth pointing out:

    Q. Do employees need to have InfoPath installed on their PCs in order to fill out forms created with InfoPath? Is InfoPath required for viewing or reading an InfoPath form?

    A. Information workers will need to have InfoPath 2003 installed on their PCs to enter information into InfoPath forms and to take advantage of the rich client functionality such as structural editing, business-logic validation, rich-text formatting, AutoCorrect, and spell-checking. That said, you can read an InfoPath form that has been saved to .MHT in your browser or within an HTML-enabled e-mail client, as the body of your mail message. Because InfoPath generates XML belonging to any customer-defined schemas, other software could be used to reuse and display that XML document.
    Q. How do users fill out an InfoPath form if they do not have InfoPath?

    A. In order to fill out forms created in InfoPath and to take advantage of InfoPath’s rich-client functionality, data validation and offline capabilities, users will need a copy of InfoPath installed on their workstation.

    It is possible to build browser-based solutions based on InfoPath forms. For example, you can build a solution in InfoPath (building a schema and Web services) that can be used for collecting information within the firewall, then use the same schema and Web services for building an ASP.NET solution for collecting information outside the firewall. For business solutions that require a “reach” (browser-based) solution, yet still use the power of InfoPath for the parts of the process that occur within an organization (where InfoPath can easily be deployed), there are two options:

    • Use ASP.NET forms in the solution to front-end the process. Data is gathered in the browser-based forms, then moved into the InfoPath forms where available. This combines the reach experience for initial data collection and the rich experience of interacting with that information via InfoPath. Customers can use the same schema and Web services for both the InfoPath and ASP.NET solutions.
    • Work with one of the many partners that have developed solutions based on InfoPath including Sourcecode, Teamplate, Ultimus and Cardiff.

    Q. Do I need to touch every desktop to deploy InfoPath? Can you host an InfoPath form in the browser?

    A. In order to fill out or design an InfoPath form, InfoPath needs to be installed on the desktop. However, once you have deployed InfoPath, you can easily roll out the form templates that users need to use InfoPath. InfoPath provides transparent deployment and maintenance of solutions via a Web-like model that downloads solutions on demand. InfoPath form templates are downloaded silently and seamlessly to the client when a user clicks on a link to an InfoPath form or clicks on an InfoPath attachment.

    A process to create an InfoPath Viewer experience if read-only is all you want: note that if you just want to be able to have a read-only rendering of an InfoPath form beyond what InfoPath can generate directly (save as MHT or via an email body), you should take a look at the SDK downlevel tool ( ) which provides a way to modify your form XML to pull in a stylesheet to use for rendering the form when InfoPath is not on the user's machine.


  • Microsoft InfoPath 2010

    InfoPath SP1 Hands-on Labs on MSDN


    The final version of InfoPath Hands-on Labs has been posted on MSDN. The labs provide an overview of InfoPath 2003 and SP1 features, and are divided into the following topics:

    • Editing forms and working with form data
    • Creating forms and layout
    • Form deployment
    • Working with controls
    • Business Logic
    • Custom controls
    • Roles
    • Working with data sources
    • Working with ADO.NET DataSets
    • Digital Signatures
    • Workflow support
    • Working with custom task panes
    • Business logic using managed code
    • External automation

    All practice files and setup instructions are included with the labs. The labs require InfoPath 2003 Service Pack-1 Preview which can be downloaded from here.

  • Microsoft InfoPath 2010

    Understanding the InfoPath SP1 URN Form Conflict Dialog


    Background on URNs

    InfoPath SP1 included changes to the mail deployment model to allow for easier ways to distribute form templates to a group.  One of the tools for making this deployment model work is the URN (Uniform Resource Name).  These URNs are generated automatically by InfoPath and should be unique for each new form template you build. 

    Note:  It’s possible to get a URN that’s identical to an existing one, but not very likely.  This will be explained more later on.

    To see the URN for your form template, you can select ‘File | Properties’ when in the Designer.  The URN is listed there as the ‘Form ID’.  It is called a Form ID because it is used in the deployment model to identify a form template that may be opened from different locations.  The URN is generated by combining three sections separated by semicolons based in part on the form template’s properties.  Here’s a sample URN:


    It consists of three parts:

    • Prefix:  [urn:schemas-microsoft-com:office:infopath]
    • Form Name (the filename by default):  [blogsample]
    • The Namespace or Namespace Timestamp:  [-myXSD-2004-05-19T20-48-18]

    Note:  The Namespace Timestamp is used whenever a user starts out building the schema within InfoPath.  If a form template is built from an XML or XSD file which has its own Namespace, then that Namespace will be used. 

    The Conflict Dialog

    Picture of the URN conflict dialog 

    This dialog will appear any time that you open a form template on your machine that has a URN that matches an existing URN that you’ve previously opened and cached, but references a different Access Path (or publish location, URL).  As you can see in the example above, I have a file called ‘blogsample.xsn’ that I’ve opened from My Documents, but the conflict dialog is saying that I’ve previously opened a file with the same URN from my Desktop.  I got myself into this situation by publishing the same form template to two separate locations with the same filename and then opening each of them.  Because the Form Name and Namespace timestamp are identical for both XSNs, so is the URN. 

    There are two options at this point.  I can either open the newer template (Version by clicking ‘Replace Form on Your Computer’ or the older one (Version by clicking ‘Keep Form on Your Computer’.  It is important to note that this dialog does not affect the original copies of these files in any way.  It will only update your local cache and it will update the file that is shown with this Form Name in your Fill Out a Form dialog.

  • Microsoft InfoPath 2010

    Collapsible Sections


    Collapsible Sections


    Mark asks:


    How do I create a collapsible section? That is, a section that can show/hide child controls, whether they are required or not. I can't use an optional section, because it requires binding.


    The easiest way to do this is to this is using Conditional Formatting. Select the Section control, then pick Format | Conditional Formatting.... Add a rule where the formatting is “Hide this control”.


    Adding conditional visibility to a section


    We often call this “conditional visibility.” Like everything in InfoPath, the view state is driven entirely by the data, so you need something in your data which maps to the expand/collapse state. One common approach is to add an attribute field to the group element the section is bound to. It shows up in your data when saved, and the expand/collapse state is saved when users save the form.


    Designing a collapsible section


    Bind a checkbox to the attribute, and you now have UI which lets the user control the state. If you prefer a button, you can create a rule which sets the value of the attribute; use two buttons with more conditional visibility rules to swap the label (e.g. between a + and a – to look like a TreeView). You can also write code which modifies the value of the attribute, and the section will show or hide.


  • Microsoft InfoPath 2010

    Upgrading InfoPath 2007 forms with Person/Group Pickers to InfoPath 2010


    Hi, this is Frank Mueller again and this is the second of two posts that I’ve written about the InfoPath 2010 Person / Group picker control. InfoPath 2007 form templates containing the Person/Group Picker control (formerly named Contact Selector) will continue to work in InfoPath 2010 the same way they used to as long as the form template remains in the InfoPath 2007 Form Template format. However, if you wish to upgrade your form template to InfoPath 2010 to take advantage of newly added functionality for the control (see this blog post for more details) or other exciting new features, you will have to perform the steps outlined in this post in order to use the Person/Group Picker.

    If you follow the steps outlined in this blog post to change your form template, you are changing the data schema of the form template. This means you will not be able to view any previously filled out forms with the new form template. In order to avoid data loss, you should create a new InfoPath 2010 version of your form template and publish it to a different location. This way you can continue to view previously filled out forms with the InfoPath 2007 version of your form template.

    Saving the form template in InfoPath 2010 form template format

    1. Click the File button and select Save As
    2. In the Save As dialog select the corresponding InfoPath 2010 Web Browser or Filler Form Template in the Save as type dropdown.
    3. Change the file name to be something different so that you don’t overwrite your existing form template
    4. Click Save

    Removing existing versions of the control from the form

    After the form template is saved in the new format, you will notice that each Person/Group Picker in your view will show the following error message when you hover your mouse cursor over it.

    Incompatibility error visual

    Also the Design Checker task pane appears, indicating that the version of the Person/Group Pickers in the view is not compatible with InfoPath 2010. For each Person/Group Picker in all views, do the following:

    1. Select the Person/Group Picker control in the view
    2. Notice that the XML node tree that the control is bound to will be highlighted in the Fields task pane (if the Fields task pane is not visible, click Show Fields on the Data tab in the Ribbon).
    3. Delete the highlighted XML node tree by deleting the root node in the Fields task pane (Right-click the node, and select Delete from the context menu)                                                   Fields Task pane
    4. Select the Person/Group Picker control in the view and delete it
    5. Use the Controls Gallery on the Home tab to insert a new Person/Group Picker at the position in the view where you just deleted the control
    6. Right-click the newly inserted control in the view and select Person/Group Picker Properties from the context menu
    7. In the Person/Group Picker Properties dialog select the SharePoint Server tab
    8. Type in the URL of the SharePoint site (If you don’t know the SharePoint site that the control used to connect to, please follow the optional steps at the end of this blog post.) Control Properties
    9. Click OK to close the dialog


    Testing the Person / Group Picker

    Preview the form in InfoPath Designer or publish the form to a SharePoint site (be sure to publish to a different location in order to be able to view previously filled out forms) and view the form, enter a name or logon alias, click the “Check Names” button and resolve the name! Alternatively you can click the “Address book” button to perform a search if you do not know the complete name of the user.

    Configuring advanced SharePoint list control properties (optional)

    To configure advanced control properties  that are new in InfoPath 2010, such as limiting the entities the control can pick, as well as requiring the control to contain data before the form can be submitted, follow the steps in this blog post.

    Determining the SharePoint site URL (optional)

    If you added the control to your InfoPath 2007 form template following the steps outlined in this blog post, you will have created a data connection called Context, which specifies the SharePoint site the Person/Group Picker should connect to. Follow these steps to recover the data connection XML file and obtain the URL of SharePoint site:

    1. Start InfoPath Designer 2010 and open your InfoPath 2007 form template
    2. Click the Data tab and select Resource Files Data Tab - Resource Files
    3. In the Resource Files dialog select Context and click on the Export button to save the data connection XML to a location on your hard drive.
    4. Open the XML file in a text editor (e.g., notepad)
    5. Write down the siteUrl to configure the Person/Group Pickers

    Frank Mueller

    InfoPath Developer

  • Microsoft InfoPath 2010

    Cool Forms! NCAA March Madness Bracket


    This week’s cool InfoPath form is a browser form used to run a bracket tournament at Microsoft. The form uses filtered dropdowns to let users make their picks for NCAA March Madness 2010, and uses conditional formatting to show correct and incorrect picks as the tournament progresses. There’s also a printable view that shows the full bracket on one page, making it easy to print your bracket and show it off to your co-workers.

    The form contains several data connections to SharePoint lists containing participants and results, which means that updating the results is as simple as editing a SharePoint list item, and doesn’t involve changing the form at all.

    Edit View (click to see larger image):

    Edit View

    Display View (click to see larger image):

    Display View

    Print View (click to see larger image):

    Print View

    For details on how we created the filtered dropdowns in this form, see Use Rules and Filters to Create Cascading Dropdowns.

    If you have a “cool” form that you would like to share with us, please send an e-mail with the following details to -

    • Attach 1 or 2 screenshots of your form
    • Provide a brief description of the form
    • You may also attach the XSN file (optional)

    The most popular submissions will be featured on our blog in future posts.

    Check out other Cool Forms! here.

  • Microsoft InfoPath 2010

    Package and Re-use a SharePoint List Solution


    This week’s post continues the theme of SharePoint list customization. In this short video demo, Roberto Taboada from the InfoPath program management team shows how you can quickly and easily re-use your customized SharePoint lists by packaging them as SharePoint list templates. This is a really powerful feature as it allows you to build and customize your SharePoint solutions once and re-use them as many times as you want.

    Get Microsoft Silverlight

    To learn more about customizing your SharePoint list forms in InfoPath, check out our earlier blog posts on the subject.

  • Microsoft InfoPath 2010

    Cool Forms! Feature Status


    This week’s cool form is a form used to track the status of testing of feature areas. One interesting decision made in this form is to use questions as labels rather than field names. This makes the form much easier to understand, particularly given that field names for compactness in the list view tend to be only one or two words. Another key aspect of this form design is the use of ‘?’ picture buttons beside certain questions. Clicking one of these buttons provides detailed help text underneath the question. You can see an example of this text in the screenshot in blue. This technique of hiding detailed text until the user asks for it enables the form designer to get the best of both worlds, a form that is compact and easy to read as well as a form that provides enough detail to ensure it is filled out correctly.

    Feature Status Form

    If you have a “cool” form that you would like to share with us, please send an e-mail with the following details to -

    • Attach 1 or 2 screenshots of your form
    • Provide a brief description of the form
    • You may also attach the XSN file (optional)

    The most popular submissions will be featured on our blog in future posts.

    Check out other Cool Forms here.

  • Microsoft InfoPath 2010

    Manage data in your SharePoint Lists using the InfoPath Form Web Part


    One of the powerful new features in InfoPath 2010 is the InfoPath Form Web Part.

    This is the 1st in a series of videos where we will show how to use the InfoPath Form Web Part to create rich mashups on portal pages in SharePoint, without writing a single line of code. In this video, Nick Dallett, a program manager lead on the InfoPath team, will demo two simple scenarios for managing data in your SharePoint lists using the InfoPath Form Web Part.


    Get Microsoft Silverlight


  • Microsoft InfoPath 2010

    Designing browser-enabled forms for performance in InfoPath Forms Services (Part 3)


    Part 3 – Postbacks and the conditions that make them expensive

    Welcome to the third article in our series on optimizing the performance of InfoPath browser-enabled forms. In our first article, we defined performance in terms of responsiveness (and identified postbacks as a major cause of poor performance). In our second article we listed a number of conditions that cause postbacks. This article continues our examination of postbacks, looking at conditions that make postbacks more expensive, reducing the responsiveness and scalability of a form system.

    What is an “expensive” postback?

    So what do we mean when we say a postback is “expensive”? Simply that it uses more server resources and takes more time to process the request and generate a response. For an individual form session, the result might be that form updates feel sluggish to the user. For a server processing many requests, the result might be that the performance of all requests is reduced as more resources are consumed.

    Most issues that involve expensive postbacks happen when the server must process form data changes, execute data connections, or run business logic that involves form code and event handlers. Postbacks are also more expensive when the amount of data is large, such as when there are attachments or pictures, digital signatures, or when the form is large and contains a lot of XML. Also, complicated XPaths or inefficient schema constructs demand additional processing resources. These conditions are exacerbated when they require SQL Session state management.

    The following items are some of the things that can increase the cost of postbacks.

    Session state

    For InfoPath Form Services, session state is a mechanism for maintaining the state of a form during a user’s form-filling session. For each session, it contains information about both the form data and the state of the form itself. Form Services uses session state to coordinate form changes between the browser and the form server and to improve server performance by reducing the communication required to synchronize them.

    This session state data is maintained in a SQL Server database by the Session State service, a shared service used by Form Services to keep track of open sessions for each form user connected to the server. This shared service is implemented by the underlying ASP.NET Session state for the farm rather than InfoPath Form Services, so if other Office products are deployed on the same server, the session service may also be used to maintain the state of user sessions for those applications as well. Depending on the server load, this could lead to contention for server resources between InfoPath Form Services and other products.

    Maintaining session state data in a SQL Server database helps improve network bandwidth by reducing the communication between the browser and the Web Front End (WFE) server. However, there is a cumulative performance impact on the WFE and computer running SQL Server as the number and size of the sessions increase. As a user’s session data grows, transferring, loading, and saving the session data takes longer, and more memory is consumed on the WFE. One way session size can grow happens when a user opens multiple forms in the same browser session. In this case, data for each form is combined in a single session, which reduces performance due to the large amount of session data that must be managed. The best way to avoid this condition is to add a button on the form that submits and closes the form (quitting the browser also closes the session, but adding a button allows users to keep their browser open after completing their work in the form). If the computer running SQL Server is separate from the server running Forms Services, which is common, then there is also an impact on the communication channel between the SQL Server and WFE servers. This can quickly become a bottleneck when a large number of multiple concurrent sessions must be managed.

    For smaller sessions, InfoPath Form Services can use Form View as an alternate method for managing the state of a session. Form View is implemented by using ASP.NET View State and the session data is kept as part of the HTML page and sent from the browser to the server on every postback rather than being kept in the SQL Server database. The Form View session is maintained on the browser side, and all session data is included in each postback to the server, up to a default maximum size of 40KB. If the View State session data grows above 40KB, it automatically switches to session state and is managed using the session state database on the SQL Server of the farm. Form View uses more network bandwidth than session state, but decreases load of the computer running SQL Server or the communication channel between servers. Consequently, for environments with smaller groups of users, we recommend configuring InfoPath Form Services to use Form view. For environments that must support many users, session state reduces the exchange of View State session data, reducing the size of postbacks, and generally produces the best performance.

    There are several specific conditions that increase the size of a session, making postbacks more expensive due to the added session state management load. For each postback request, the form’s state must be restored on the server, then all changes must be processed, saved, and sent back in a response to the browser. The form’s state is stored in either View state or Session state and needs to be restored by server when the next postback request for the form comes from the browser. The larger the amount of data involved, the more it slows down saving and restoring form state on each postback.

    • Data Adapters
      • When a data connection returns data, it is stored in the form’s state, either View state for small sessions or the session state database for larger sessions. The larger the amount of data, the more it slows loading and saving updates to the session state database and the form XML.

    • Attachments or pictures
      • A file attachment control increases the maximum session size by 50 percent. If the maximum size is normally set at 4MB, adding an attachment control to the form template increases it to 6MB. This additional space is allocated to accommodate the base64 encoded binary data of the attachment.

      • Consider the number of attachment controls you add to the form template, especially if the attachments or pictures might be large.

      • If you expect that number of forms sessions with large attachments or pictures will be low, the performance impact will be limited to individual editing sessions. If you expect that many of the sessions will contain large attachments, the performance hit is more likely to reduce the scalability of your form system.

      • If you need to accommodate multiple attachments, or very large attachments, you might want to investigate developing a custom solution so that attachments are not stored in the form, but are stored in a location outside the form, such as a SharePoint document library or a database.

    • Digital Signatures
      • Multiple signatures can inflate the data size of an XML form by 500KB or more for each signature. Each signature is stored as base64 encoded data.

      • Although Internet Explorer uses an ActiveX control to handle signatures and other browsers embed the signature in the form, all signatures increase the size of the session. For all browsers, the added size of forms containing digital signatures makes postbacks more expensive.

    Submitting forms to a SharePoint library

    Completed forms are commonly submitted to a SharePoint library. However, libraries are limited to 2000 documents per folder, so as this limit is approached, you will see performance problems. If you anticipate reaching that limit, you can design your form system to submit to an alternate destination. The simplest approach is to make sure that each type of form submits to a separate SharePoint library or folder rather a single library or folder containing multiple types of forms; this approach only defers the problem though. Another alternative might be to use a workflow to move submitted files from the library. A more sophisticated approach is to submit to a Web service. This will require custom development for the Web service, but it allows the most flexibility and scalability since the completed forms can be stored in either a SharePoint library or in a database. A solution that submits through a Web service to a database offers the best performance and scalability for large form systems.

    First request optimization

    InfoPath Form Services uses a technique called first request optimization to improve the loading performance of a form the first time it is requested. First request optimization involves pre-rendering an instance of the form from the form template when the form template is published. This form instance does not require a session state database entry (because there is no user session yet for an initial request). When first requested by a user, the pre-rendered instance of the form is sent to the browser for rendering so the user doesn’t have to wait while the server initializes the session and loads its version of the form.

    However, there are form features that will disable first request optimization. Initial requests for forms that cannot use first request optimization are more expensive, reducing responsiveness and slowing the loading of the form. The following conditions are examples of things that prevent this optimization:

    • The use of current time and data functions as default values

    • Secondary data source queries that execute on load (except XML files that are part of the form)

    • Rules or business logic that run on load

    • The use of a username for a default value

    • Any other environment-related or dynamic information that requires server processing

    When you publish a new form template, you can determine whether first request optimization is being used by checking for the presence of an ASP.NET session ID cookie immediately after requesting a new form (you can use an HTTP scanner tool such as Fiddler2 to check for the cookie in the response). If there is no cookie, then the form is using first request optimization. Perform an action that triggers a postback, such as switching views, and you will find a session ID cookie.

    Business logic changes to XML and cascading events

    When a postback involves business logic that makes changes to the form XML on the server, each change to the XML causes events to fire. This can cause an expensive chain of processing operations if the event handling is set up so that an XML change causes a cascade of events that make additional XML changes. Although the number of nested changes is restricted, there is no restriction on how many XML nodes are changed by a single event listener. Consequently, if an event listener changes more than one XML node and each change causes other listeners to fire and make changes to other XML nodes, then the total number of events invoked and XML changes made could be significant. The processing required to execute the cascade of events can use significant server resources, reducing throughput, scalability, and responsiveness. This situation is similar to the event handling issue discussed in the previous article on causes of postbacks, and likewise, it is important for performance and scalability that you understand and carefully scope events to reduce unnecessary server stress.

    Custom hosting pages

    Another issue discussed in the previous article on causes of postbacks addresses an advanced form scenario that involves using a custom ASP.NET page to host the InfoPath Form control. Since the emphasis here is on conditions that make postbacks more expensive, it is worth noting that although a custom solution offers significant flexibility, you also give up some of the optimizations provided for forms published using the InfoPath Form Designer. One of the optimizations you lose is that postbacks that need to communicate with the hosting page cannot communicate using partial postbacks, and instead must use more expensive full page postbacks. However, if the hosting page just needs to display a form (but doesn’t need to listen for a submit to host event), then there is no change in the form’s postback behavior and partial postbacks can be used. Also, as noted previously, with each postback there is additional processing on the server because the ASP.NET page controls must be rebuilt; and if the page is hosted on a SharePoint site, it also must initialize the complete SharePoint page infrastructure as well.

    Additional considerations

    As you might expect, this list of conditions that can make postbacks an expensive operation is not comprehensive. In fact, almost any postback can be expensive, depending on type and extent of the changes involved. We’ve highlighted some important issues above and in the previous article on postbacks. If you consider the other issues listed in that article - complex calculations and XPaths, out-of-context and multiple binding - you can see that they also imply performance and scalability impacts arising from expensive processing operations on the form server. If something causes a postback because it requires the processing power of the server, then it necessarily adds to the server load, affecting resource utilization, throughput, and scalability. These issues become more important as the number of concurrent users increases, and as the size and complexity of the forms increases.

    What’s next?

    The next article in our series on understanding and optimizing the performance of browser-enabled forms will address conditions that affect form rendering in the browser. We’ll also look at an important tool provided by the InfoPath Designer for optimizing browser-enabled forms and controlling postbacks, the Design Checker.


  • Microsoft InfoPath 2010

    Designing browser-enabled forms for performance in InfoPath Forms Services (Part 4)


    Part 4 – Browser Rendering Issues

    Welcome to the fourth article in our series on optimizing the performance of InfoPath browser-enabled forms. In our previous articles we defined performance in terms of responsiveness, listed a number of conditions that cause postbacks, and looked at some of conditions that make postbacks more expensive, reducing the responsiveness and scalability of a form system. In this article we’ll examine some of the issues that affect form rendering performance in the browser. We’ll also take a quick look at using the Design Checker to monitor browser compatibility issues while designing a form template in the InfoPath Designer.

    Conditions that slow form rendering in the browser

    There a several conditions that can reduce form-rendering performance in the browser. The main effect of these conditions is that the user experiences delays and sluggishness when working with the form. The reduced performance experienced because of slow form rendering in the browser generally occurs at the following times:

    • When the form initially loads

    • When the form is updated and re-rendered after a postback response

    • When there is a change to the display of the form in the browser that does not involve a postback

    If the designer can reduce or eliminate conditions that are more expensive for the browser to render, the form will render more quickly, and feel more responsive to the user. As with other design issues we’ve examined that affect postbacks and server performance and scalability, addressing performance issues that affect browser rendering must be balanced with your unique design and business requirements.

    • Rich Text Box control

      The Rich Text Box control creates HTML elements for the content added to a rich text field. Depending on the amount of content and formatting added by the user it can end up creating a large number of HTML elements, which can impact browser performance. One issue with using a rich text field is that you cannot predict how much data a form user might add to the field. For example, a user could paste a large rich text selection into your form from just about any source. Although the Rich Text Box control for a browser-enabled form does not allow embedded images, only linked images, the content could still be quite large.

      Unfortunately, for browser-enabled forms the InfoPath Designer does not provide a way to limit the amount of data entered. Consequently, you should consider carefully how your users are likely to use any rich text fields you add to the form and limit the number of rich text fields that are visible in a view. If you need multiple rich text fields, consider using multiple views rather than putting them all on a single view. As an alternative, consider using a Multi-line Text Box control instead.

    • Nested Tables

      Rendering HTML code for tables is a relatively expensive operation for a browser. Nesting tables by inserting one table inside another, especially if they are nested several levels deep, compounds the complexity and is generally slow for a browser to render. For better rendering performance, consider using adjacent non-nested tables rather than nested tables.

    • Conditional formatting

      We looked at conditional formatting in an earlier article, touching on the interaction with postbacks to the server and how conditional formatting expressions fire each time the form is re-rendered. Since the browser must manipulate all the data, whether it is visible or not, this can be an expensive operation that makes the form display feel less responsive. While conditional formatting can be a useful design tool, there are times when the performance cost may outweigh the benefits. For example, if a form contains a large amount of data and a substantial part is hidden, the conditional formatting can slow the form display even though some of it isn’t rendered.

      In this case, designing the form with multiple views might improve the form’s display performance compared to the single view with hidden content. Although it will cause a postback each time there is a switch to another view, the user’s interaction with each of those views in the browser may feel more responsive. This is because each view has a smaller amount of data to render than the single view containing hidden data. The tradeoff you need to consider here is between the browser-side responsiveness of the form display and the server-side scalability of your form system as it processes postbacks: using conditional visibility might slow form display, but reduce the number of server requests, while using multiple views improves form display, but increases server requests and reduces scalability.

      As another example of how subtle performance tradeoffs can be, as noted in the earlier article, it is also possible to have a design where the form display is more responsive if it uses conditional formatting to hide some data. This is happens in a situation where the browser actually takes longer to render all the elements than it takes to process the conditional formatting and hide some.

      If you suspect you have a situation where conditional formatting could either help or hinder your form’s performance in the browser – or your server scalability – try alternate designs and test them to determine which design best meets your requirements.

    • Drop-Down List Box controls with many items

      Drop-Down List Box controls can generate a large amount of HTML, especially when there many items provided in the list. The amount of HTML balloons when the list control is contained in a repeating section or table. For example, if you include 50 items in a list, and the list is repeated 50 times, the underlying HTML code will grow very rapidly and slow down rendering of the form! Try to limit the number items in lists that are used in repeating elements or limit the number of repeating elements. Alternatively, you can try using conditional formatting, putting the repeating elements containing drop-down lists into a section that is hidden by default. Because they are not supported in browser-enabled forms, some of workarounds you might consider using if you are familiar with InfoPath rich-client forms, such as a Master-Detail control or one of the other list controls, are not available. About the only other alternative might be to emulate the list using a repeating table with each item on a row (and some fancy formatting). One situation to watch out for is using an external data source to provide the list items. If you need to do this, then you also need to make sure the number of items provided by the data source is limited to a reasonable number. As with any design, it is always a recommended best practice to test alternative designs for expected (and exceptional) data sizes to determine how your form designs perform.

    • Many visible controls

      Forms that have a large number of InfoPath controls visible in a view will reduce browser performance. Again, this is amplified when the controls are in repeating sections or tables. The first suggestion is to use multiple views so that each view has fewer controls to be rendered. If you use multiple views, make sure that controls are only bound once in the view in which they are used (use the Design Checker). Once again, you can also use conditional formatting to hide some of the controls, but this will typically achieve a smaller gain in browser performance compared to using multiple views. Because there are a number of important variables that determine browser rendering performance, your design alternatives should be tested in the common user environments you expect (data size, browser type, user's machine configuration) to determine acceptable number of controls and the relative performance of each design.

    • Calculations that use large data sets

      If you design a form that includes calculations and the data for the calculations is loaded from an external data source, then that data will be downloaded to the browser so that the calculation can run in the browser without a postback to the server. Normally this strategy improves overall performance by reducing postbacks. However, if the data set is large, the benefit of eliminating postbacks can be overtaken by the performance cost of handling the data in the browser. First, it is more expensive to load a large data set; second, it is expensive to run after it is loaded.

      If you find that the browser is too slow when running calculations with large data sets, you can force a postback so that the calculation runs on the server instead. In the InfoPath Designer, for the field that runs the calculation, add a button and change the postback setting to always require a postback. When the user clicks the button to run the calculation, it will postback to the server to evaluate the calculation and return the result to the browser for display. Like most performance suggestions, you need to balance performance in the browser with the performance and scalability of your form server system.

    • Reporting scenarios

      InfoPath is primarily designed to address form-filling scenarios. Although it can also be used to display data in a reporting scenario, this can have a negative impact on browser performance as the amount of data downloaded for display increases. If there is a possibility that the amount of data could be very large, then you can expect performance problems not only in the browser, but also on the server. Depending your ability to predict and limit the amount of data in a reporting form, it might be possible to maintain acceptable performance by using multiple views and read-only controls. However, if the data is too large or cannot be limited practically, you should consider an alternate reporting solution.

    • Internet Explorer 6

      If you have form users that are using Internet Explorer 6, they will experience reduced browser performance compared with other browsers due to known issues with IE6 JavaScript performance. You might consider providing a statement on your site about browser support, and if you know you have a substantial number of users running IE6, then it is a good practice to include IE6 performance testing in your development plans.

    Use the Design Checker to monitor browser compatibility issues

    The InfoPath Designer allows you to design forms that run in both the rich-client and a browser. When you are designing browser-enabled forms, and especially when you want your form to support running in both environments, you need to be careful about browser compatibility issues. As you are designing a form template in the InfoPath Designer, you can use the Design Checker task pane to monitor any browser compatibility issues detected by InfoPath, including those that affect performance.

    Among the messages displayed by the Design Checker are warnings for controls that will trigger postbacks to the server (these messages are hidden by default; to view them, select "Browser Optimization Messages" from the Options button at the bottom of the Design Checker). One or messages can appear for each control that will post back to the server when the value of the control changes.

    Sometimes the postback occurs because of a calculation, binding, or other expression on that control. Occasionally a control will post back to the server not because of a property on that control, but because that control is contained inside a section or a table where some other control forces a postback, or the control contains a section, table, or other controls inside it that cause a postback. In these cases, the warning messages indicate that you should look for another control marked as a primary cause of the postback; examining the messages for that control can help you locate, understand, and control postbacks caused by related controls.

    If having other controls bound to the same element or group are causing unwanted postbacks, consider using separate views, with the control bound once in each view.

    To resolve issues where the binding of the control requires server evaluation, or a node is listed as only available on the server, you might need to simplify your schema.

    You can change the default postback behavior for an individual control using the Postback settings options on the Browser forms tab in the Properties window for the control. There are three options available: Never, Always, and Only when necessary for correct rendering of the form (recommended). You can reduce the number of postbacks by changing the setting to Never. If you select Never, then the control will not send data to the server on change; the data will only go to the server and formatting, calculations, etc. will only run when the form user saves or submits the form, or another control in the form causes a postback to the server. For controls you want to change, you must change the postback setting option on each control individually; changing the option on a section or group control does not automatically change the value for every control inside it.

    Note that you should carefully consider the effect of changing postback behavior to ensure that the result is acceptable for your environment. Be careful about suppressing postbacks that affect the user’s form-filling experience to avoid issues where displayed data could be incorrect. You never want to sacrifice data integrity for a potential gain in performance. If you make any change to the postback settings, it should be thoroughly tested to ensure the form behaves correctly.

    What’s next?

    The next article in our series provides information on some of the useful performance monitoring counters that can help you evaluate the performance of your form system.

  • Microsoft InfoPath 2010

    Template Parts 101


    So, you’ve heard about this new InfoPath 2007 feature called template parts. You may have even found the option to design one in the Design a Form Template dialog. But what you can do with it and why you would want to bother.. well that’s just a big mystery. So, I’m here to help you out.

    Template parts are simply mini form templates: you can add layout, controls, rules, data validation, conditional formatting and data connections. Once built, you can include template parts in other form templates so that you only have to build common components once. When you need to make changes, you change the template part and then update its version within the form templates using it. You don’t have to make the modification numerous times. Common scenarios for template part use include:

    • Company letterhead
    • Employee information (address, phone number)
    • Purchase order

    How to build a template part

    Template parts are built in the same way that form templates are built, though there is a slight difference in how you get started. Because there are some limitations in what you can put into a template part (see "What template parts don’t do" below), they are built in a separate mode from regular form templates. This allows you to be sure that whatever you put into the template part will function as intended. At the Design a Form Template dialog, select the Template Part radio button:

    Note that you can also choose whether or not the template part will be used in browser-enabled forms. If you aren’t sure, err on the side of caution and select “Enable browser-compatible features only”. This will ensure that you can use the template part in both client-based and browser-compatible forms.

    Click OK and you can now design your template part as you would any other form template. When you are finished, save the template part (you will end up with a file ending in .xtp) and send it out to whoever you would like to use it.

    How to use a template part

    To actually put a template part into a form, you must first install it on your machine. This sounds a whole lot scarier than it actually is. All you need to do is click on the “Add or Remove Custom Controls…” link at the bottom of the Controls task pane and follow the instructions that appear:

    Once you’ve done this, the template part will show up in the Custom Controls area of the Controls task pane. You can now insert the template part into your form as you would any other control. Once your template part has been inserted, you can also make modifications to it that are specific to that form.

    How to update a template part

    When you make changes to a template part that is already in use, you must redistribute the template part. The people using it must then install the new version (see “How to use a template part” above) and update the ones in their forms. Once the new version is installed, template parts in the form will automatically notice that there is a newer version available. You can then right-click on the template part and select Update. If you have made any changes to the template part within the form itself, these changes will be overwritten by the update.

    What template parts don’t do

    Here are some of the things that you can’t do with template parts:

    • Script and managed code
    • ActiveX controls
    • Submit data connections
    • IRM
    • Multiple views

    The more complete list is available on Office Online. The general pattern is that anything that would be a form-level property is not available in template parts.

    I hope you will find template parts to be useful and a mite less mysterious than they were before.

    Happy form designing,

    Bojana Marjanovic
    Program Manager

  • Microsoft InfoPath 2010

    Using the Events Manager of the InfoPath Hosted Control


    The InfoPath hosted control gives developers of third party hosted applications the ability to respond to events in the form.  The InfoPath event manager provides this functionality.  Through the event manager a host application can respond to 5 form events, 3 xml events and 1 control event:

    Form Events

    Xml Events

    Control Events

    Saving event
    Context Changed event
    Sign event
    Merging event
    View Switched event

    Changing event
    Validating event
    Changed event

    Clicking event

    How can third party host applications use the event manager?

    Step 1: Implement an InternalStartup method

    First, add code to handle the InternalStartup event. InternalStartup method will execute when a form loads.

    public Form1()
                //sync to the startup event where you can register for individual events
                formControl1.InternalStartup += new Microsoft.Office.InfoPath.FormControl.EventHandler<EventArgs>(InternalStartup);

    Next, implement your InternalStartup method. The function signature should look similar to:

    void formControl1_InternalStartup(object sender, EventArgs e)


    Step 2: Register to receive events

    In your InternalStartup method add code to register for events. For form events this code looks like this.

    void InternalStartup(object sender, EventArgs e)
           ((FormControl)sender).EventManager.FormEvents.ViewSwitched += new ViewSwitchedEventHandler(OnSwitchView);
           ((FormControl)sender).EventManager.FormEvents.Submit       += new SubmitEventHandler(OnSubmit);
           ((FormControl)sender).EventManager.FormEvents.Sign         += new SignEventHandler(OnSign);
           ((FormControl)sender).EventManager.FormEvents.Save         += new SaveEventHandler(OnSave);
           ((FormControl)sender).EventManager.FormEvents.Merge        += new MergeEventHandler(OnMerge);

    For xml events you must provide the XPath of the node whose events you wish to respond to. Below is a sample of how to register to receive xml events.


    void InternalStartup(object sender, EventArgs e)
          ((FormControl)sender).EventManager.XmlEvents["/my:myFields/my:field1"].Changed    += new XmlChangedEventHandler(FieldChanged);
          ((FormControl)sender).EventManager.XmlEvents["/my:myFields/my:field1"].Changing   += new XmlChangingEventHandler(FieldChanging);
          ((FormControl)sender).EventManager.XmlEvents["/my:myFields/my:field1"].Validating += new XmlValidatingEventHandler(FieldValidating);

    To receive the click event for a button you must specify the control id of the button. Below is a sample of how to register to receive control events.

    void InternalStartup(object sender, EventArgs e)
          ((ButtonEvent)((FormControl)sender).EventManager.ControlEvents["CTRL2_5"]).Clicked += new ClickedEventHandler(ButtonClicked);


    Step 3: Implement methods to handle each event registered

    The final step is to implement handlers for the events you have registered for.
    The handlers for the events have the following method signatures.

    Form Events

    public delegate void ViewSwitchedEventHandler(object sender, Microsoft.Office.InfoPath.ViewSwitchedEventArgs e)
    public delegate void SubmitEventHandler(object sender, Microsoft.Office.InfoPath.SubmitEventArgs e)
    public delegate void SignEventHandler(object sender, Microsoft.Office.InfoPath.SignEventArgs e)
    public delegate void SaveEventHandler(object sender, Microsoft.Office.InfoPath.SaveEventArgs e)
    public delegate void MergeEventHandler(object sender, Microsoft.Office.InfoPath.MergeEventArgs e)

    Xml Events

    public delegate void XmlChangedEventHandler(object sender, Microsoft.Office.InfoPath.XmlEventArgs e)
    public delegate void XmlChangingEventHandler(object sender, Microsoft.Office.InfoPath.XmlChangingEventArgs e)
    public delegate void XmlValidatingEventHandler(object sender, Microsoft.Office.InfoPath.XmlValidatingEventArgs e)

    Control Events

    public delegate void ClickedEventHandler(object sender, Microsoft.Office.InfoPath.ClickedEventArgs e)

    Example: changed event, view switched event, button clicked event.

    void FieldChanged(object sender, XmlEventArgs e) {}
    void OnSwitchView(object sender, ViewSwitchedEventArgs e) {}
    void button1_Click(object sender, EventArgs e) {}


    Things to know about handling events

    1. Events are handled first by the form’s business logic, then by others who register to handle events. Since events are handled asynchronously it is possible that the code in the business logic may cancel the event, and deny the host the opportunity to handle the event.
    2. In order to handle the submit, save and merging events, the designer of the form template must specify that the event is to be handled through the use of code. Without enabling this in the form template the event will not be handled in code.
    3. Buttons must specify that clicks be handled through code or the event will not be handled through code.
    4. The sign event will only take place when the form is fully trusted.
    5. The Loading and VersionUpgrade events are not available from third party hosted applications as these events occur before the form is loaded in the hosted application.

    DeVere Dyett
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    Sniffing Code in Form Templates


    With the introduction of InfoPath Forms Services for MOSS 2007, clever management of form template deployment will probably become a must for most IT departments.  You'll want to be sure that form templates are not draining server resources.  You'll especially want to keep an eye on administrator-deployed form templates, as those can achieve fully trusted status and execute arbitrary code on the server.

    With that in mind, it's probably a good idea to set up a code review process for InfoPath form templates that will be deployed by the administrator.  To facilitate the process, it might be nice to have a tool around that will tell you whether or not a form template uses custom code.  This is pretty easy to determine, and a tool can be coded up rather quickly, but we figured we'd facilitate the process and provide a sample to get you going.  And here it is…

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Xml;
    using System.Xml.XPath;
    using System.IO;
    using System.Diagnostics;

    namespace CheckForCode
    class Program
    /// <summary>
    /// The Main method entry point for the code-checking algorithm.
    /// </summary>
    /// <param name="args">The command-line arguments for the code-checking algorithm.</param>
    public static void Main(string[] args)
    if (args == null || args.Length == 0)
    Console.WriteLine("No arguments specified.");
    string filePath = args[0];
    Uri fileUri = new Uri(filePath, UriKind.Absolute);
    filePath = fileUri.AbsoluteUri;
    // If the file is an http URL, download it to the local machine.
    if (fileUri.Scheme.Equals(Uri.UriSchemeHttp))
    filePath = CopyFormTemplateLocally(filePath);
    if (File.Exists(filePath))
    string extension = Path.GetExtension(filePath);
    if (extension.Equals(".xsn", StringComparison.CurrentCultureIgnoreCase))
    // Extract the xsf and check for the root assembly.
    string pathToXSF = ExpandManifest(filePath);
    else if (extension.Equals(".xsf", StringComparison.CurrentCultureIgnoreCase))
    // Check for the root assembly.
    catch(ArgumentException exn)
    Console.WriteLine("The file path argument is invalid.");
    Console.WriteLine("Exception message: " + exn.Message);
    catch(UriFormatException exn)
    Console.WriteLine("The file path is not a valid Uri: '" + filePath + "'");
    Console.WriteLine("Exception message: " + exn.Message);
    Console.WriteLine("Hit any key to exit.");
    /// <summary>
    /// Get the path to the temp folder for the current user.
    /// </summary>
    private static string TempFolder
    string tempFolder = Environment.ExpandEnvironmentVariables("%temp%");
    return tempFolder;
    /// <summary>
    /// Copy a form template at an http URL to a local path.
    /// </summary>
    /// <param name="absoluteFileUri">The absolute Uri of the form template.</param>
    /// <returns>The local path where the form template was downloaded.</returns>
    private static string CopyFormTemplateLocally(string absoluteFileUri)
    string fileName = Path.GetFileName(absoluteFileUri);
    string tempFilePath = Path.Combine(TempFolder, fileName);
    // Download the form template source from the server.
    System.Net.WebClient client = new System.Net.WebClient();
    client.UseDefaultCredentials = true;
    client.DownloadFile(absoluteFileUri, tempFilePath);
    return tempFilePath;
    /// <summary>
    /// Expand the manifest.xsf file from the specified xsn.
    /// </summary>
    /// <param name="pathToXSN">The absolute path to the xsn.</param>
    /// <returns>The path to the expanded xsf.</returns>
    private static string ExpandManifest(string pathToXSN)
    string tempFolder = TempFolder;
    Process expand = new Process();
    expand.StartInfo.ErrorDialog = false;
    expand.StartInfo.UseShellExecute = false;
    expand.StartInfo.RedirectStandardOutput = true;
    expand.StartInfo.CreateNoWindow = true;
    expand.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    expand.StartInfo.FileName = "expand.exe";
    expand.StartInfo.Arguments = pathToXSN + " -F:manifest.xsf " + tempFolder;
    // Note that the xsf may not be named "manifest" so this could fail if the user
    // has extracted the form template files and changed the name of the file.
    return Path.Combine(tempFolder, "manifest.xsf");
    /// <summary>
    /// Check the xsf at the specified path for a root assembly dll.
    /// </summary>
    /// <param name="pathToXSF">The absolute path to the xsf document.</param>
    private static void CheckXSFForCode(string pathToXSF)
    string rootAssemblyNameXPath = "/xsf:xDocumentClass/xsf:package/xsf:files/xsf:file[xsf:fileProperties/xsf:property/@value='rootAssembly']/@name";
    // Load the xsf document.
    XmlDocument xsfDocument = new XmlDocument();
    // Load the xsf namespace.
    XmlNamespaceManager nameSpaceManager = new XmlNamespaceManager(xsfDocument.NameTable);
    nameSpaceManager.AddNamespace("xsf", "");
    // Navigate to the root assembly, if it exists.
    XPathNavigator xsfRootNavigator = xsfDocument.CreateNavigator();
    XPathNavigator assemblyFile = xsfRootNavigator.SelectSingleNode(rootAssemblyNameXPath, nameSpaceManager);
    // Alert for code review.
    if (null == assemblyFile)
    Console.WriteLine("No custom code in form template.");
    Console.WriteLine("Code review required! Root assembly name: " + assemblyFile.Value);

    Just slap this into a console application in Visual Studio 2005, and you'll have a simple application that will accept the Uri of the form template or xsf as input and output "No code" or "Code found!"  With a little customization, something like this could be worked into a workflow that would govern the deployment of administrator-deployed form templates.

    And taking it a bit further, you could automatically seek out the source code folder in the "manifest.xsf" file, in the "projectPath" attribute of the "xsf2:managedCode" element.  Note here, though, that it will only be accessible if the form designer stored the VSTA project in a shared location, so you may have to implement some administrator policies to guarantee that this location is accessible.

    Forrest Dillaway
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    UDC File Authoring Tool


    Some time ago, we blogged about the reasons why you'd use UDC files and the anatomy of UDC files. You may be wondering, however, if it's possible to author these files in InfoPath - after all, UDC files are just XML files.

    You're right - this is definitely possible. Attached to this article is a form template that lets you author and edit UDC files. Here are the steps you need to take to make it work:

    1) Download the attached form template, save it to your desktop

    2) Right-click on the downloaded .xsn file, then select Design. Ignore any warnings about the published location.

    3) Go to File | Publish | Network Location, and republish the form template. Then open the form template from its published location.

    Enjoy, and let us know if you have any feedback on the tool.

    Nick Dallett
    Lead Program Manager
    Travis Rhodes
    Software Design Engineer in Test
  • Microsoft InfoPath 2010

    Relinking forms and form templates


    We often see issues when people move forms and templates from one location to another. In fact, the linked nature of InfoPath forms and templates is probably one of the hardest aspects of InfoPath to understand. While the complexities can sometimes seem burdensome, the truth is that the overall model is actually quite simple. Once understood, all it takes is a few small tricks and you will find that moving forms and templates isn’t really that difficult. Moveover, you will have a much better understanding of how InfoPath works.

    The Basics

    InfoPath works by associating a form instance with a form template. The way we do this is typically through a URL association. When you design a form template, it stores the entire description of how the form functions. When published, the form template is put in a location we refer to as the publishUrl (though we expose this in the publish wizard as the access path). Regardless of the name, the key point is that the form template resides in a well known location. 

    Once published, the form template can be used to create new form instances, or just forms. When you create a form against InfoPath, we save the data as straight XML and associate this XML with the form template via a URL. With the URL we know how to associate the form design (layout, business logic, validation, code, etc) with the form.

    The Diagnosis

    As you would expect, things get wonky when the association fails to resolve correctly. This typically manifests itself in one of two ways:
    1) A form won’t seem to update itself when you publish a new version
    2) A form just plain won’t open

    You can usually tell pretty quickly if this is really the issue by creating a new form from the published form template and comparing the processing instructions (PI’s) between the old forms and the newly created form. What you are looking for is this (I have omitted some content for clarity):

    <?mso-infoPathSolution solutionVersion="" productVersion="12.0.0" PIVersion="" href="http://server/site/template.xsn"?>

    If the two form files don’t have the same href attribute in the PI, then you have yourself a linking issue.

    The Remedy

    Once diagnosed, the problem is actually quite easy to fix and can be done in one of several ways. Let’s take a look…

    Hand Edit: The most obvious solution is to simply change the href attribute in the PI to point to the correct form template. You can do this by opening the XML file in your favorite text editor and just correcting the href attribute to point to the correct location. This works great for one or two files but is tedious and mind numbing if you have more than a handful.

    Re-Link: If your form template is in a Windows SharePoint Server form library, then you can use the built in re-link feature to manage the re-linking for you.  Simply move the forms from the old location to the new form library. Once there, you can force a re-link operation. In WSS v2, you can do this by opening the form library, selecting Modify settings and columns, and clicking on the Relink forms to this form library link. In WSS v3, you can access the re-link functionality by selecting the Relink Documents view from the View dropdown. When you perform the re-link, WSS will scan all the XML files for the href in the PI and if it doesn’t match the location for the template associated with the form library, the PI will be updated. 

    PIFix: Finally, if your forms and your form template are living on a file share somewhere, then you can use the PI Fixup tool (pifix.exe) provided in the InfoPath 2003 SDK. This tool will allow you to process any number of input files and change attributes in the form to match your target form template.  Follow the instructions in the SDK or the tool to re-link your form files.


    As with any “under the hood” job, there are caveats.  You will want to make sure you understand what you are doing so you don’t wind up with “extra parts,” as it were.  When changing forms to work against different templates, there are two major things you want to think about before you re-link:
    1) Schema changes
    2) Versioning

    Schema changes are perhaps the most serious issue because they can create data loss if you aren’t careful. By default, InfoPath enforces schema when opening forms against templates.  If the forms XML doesn’t match the schema, we don’t load it. By default, InfoPath works to address this by performing version upgrades on the XML when it doesn’t match the schema. This is great because you don’t need to worry that existing forms will break when you make changes to the form template. However, keep in mind that when elements and attributes don’t match the form template schema, existing data may be deleted to make the form schema compatible. Here is what happens:
    - Add elements/attributes: No worries. If you add elements or attributes to the form template, InfoPath silently adds the element or attribute to the form XML.
    - Delete elements/attributes: Think about it... You deleted the elements and attributes from the form template, so we will remove them from the XML file too. Chances are you didn’t need it anyway (why delete it otherwise?), but you want to pay attention here.
    - Move elements/attributes: Really think about it... When you move an item in the form template’s data source, we treat that as a delete and then an add.  So be aware that data might disappear!
    The bottom line, make sure you understand the schema implications of linking your form to a potentially different form template.

    Versioning issues can cause minor headaches but don’t impact the ability of the form to open nor contribute to possible data loss. The key here is to make sure the solution version attribute in the form’s PI is less than that of the published template. You can find the version number of your form template in the form options dialog as seen below:

    If the form’s version is higher than that of the form template, the you will simply receive a warning message when opening the form telling you that you are opening it against an older template.

    Happy re-linking!!!

    Nathaniel Stott
    Program Manager

  • Microsoft InfoPath 2010

    XPath Powers: Calculating Totals


    InfoPath makes it trivial to track totals for repeating structures, such as customer orders. Just create a repeating table of line items, and sum up the totals for individual line items. However, sometimes, totals for line items may not be available; it is still possible to perform dynamic calculations across the repeating structure, even when interim results (line item totals) are not stored in the data source. This article will explain a way to make this work without code.

    Let's explore the simple case first.

     Form at Runtime Data Source

    Line item total is set by using a default value (price * quantity) on the lineItemTotal node. Creating an order total is just a matter of adding an expression box that uses the built-in SUM function:


    And voila, we're done, totals will be calculated correctly.

    The reason why we are here: the complex case.

    What if the interim results (line item totals in our scenario) cannot be persisted in the data source? This situation might arise if you're operating on a fixed schema, or if you're an "XML purist" (I know I am :-)), arguing that there is unnecessary redundancy in your XML if you store calculated values.

    The goal is still the same - but the data source is different.

     Form at Runtime Data Source

    The line item total would be an expression box instead of the text box; it would be calculated simply as (price * quantity).

    But how do we calculate the order total? Your first instinct may suggest to use sum (price * quantity), but you'll soon discover that the SUM XPath function only takes a nodeset...

    Let's recall the clever technique of iterating through repeating items by using just XPath: it was described in detail in this article. Let's use the following value for the order total expression box:

    sum(xdMath:Eval(my:lineItems, "my:price * my:quantity"))

    Why does this work? Let's go inside-out:

    1) The eval function evaluates the price * quantity expression in the context of line items, and returns a nodeset with the results.
    2) The sum function takes in a nodeset as a parameter, and sums up its contents, giving us the desired total.

    I'm attaching a sample form template that has this technique implemented; save the XSN locally before opening it up.

    This method works in InfoPath 2003, 2007, and is supported in browser-enabled form templates.

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Sorting Repeating and Tabular Data


    InfoPath is a great way to easily gather and present XML data to the masses. But what about efficiently presenting a massive amount data? Tons of data (e.g., a list of hundreds product names) usually find their ways into lists that we’ll find on SharePoint, in a database, or just sitting in an XML file. Controls like Repeating Sections and Tables are useful mechanisms for displaying lists of data. But their usefulness is limited to how efficiently the user of your form can find and work with such large lists of data. An easy solution to effectively present large lists of data to your users is through sorting that data.

    No Sorting Options in InfoPath
    Try scouring the Repeating Table or Repeating Section controls’ properties dialogs for anything related to “sort”. Sorry to say, you’ll come up empty handed. That’s why we thought you’d find this blog entry handy. Our goal is to show you how to sort any repeating data and to do so in many different ways: sort by string, sort by number, sort ascending or descending, and even sort by different fields (or columns) in the repeating data. What we’ll show you, in both the code and the design of the view, is designed to be browser-compatible. This means you can publish this form template to a SharePoint server running Forms Services 2007 and fill out the form in a Web browser. Let’s get started.


    Figure 1: Filling out the SortingPeople sample form template

    The sample form template is attached; download the ZIP to your desktop, expand it, then right-click the XSN and select "Open in Design Mode". This sample requires InfoPath 2007, and will work in the browser when published to InfoPath Forms Services.

    The View for the SortingPeople Form Template
    To show you how to sort data in your form, we’ll use a concocted example to sort a list of people. As you can see in Figure 1, there are various options to sort the data. Clicking the “Sort” Button triggers the sort otherwise the data is not sorted automatically (more on this later). You can also sort by clicking any of the “Sort by this column” Buttons in the header and footer of any column. There are three columns in the Repeating Table representing our repeating data: Last Name, First Name, and Age. (The string data type is used for the first two columns and an integer data type for the last column.) In Figure 1, we’ve filled out the form with names of famous architects. (Their ages are fictitious.) While we’re not working with enough data to really justify a sort, this example is simply for demonstrative purposes. As you might expect, we can sort the Repeating Table data by any column and by any direction (ascending or descending). At any time we can change the existing data or even add or remove rows. But we would need to invoke the sorting functionality to put things into place again.

    The Data Source for the SortingPeople Form Template
    To begin designing this form template we started with controls and the data source. We inserted a Repeating Table control and renamed its data source groups and fields to map with our people example. The main data source is shown in Figure 2. To accommodate the various sorting options that we expose via controls at the top of the view (e.g., the Sort By Drop-Down List Box), we’ve added attribute fields under the SortingPeople document element. These attribute fields remember, for example, whether we’re sorting by the Last Name or the Age column.

    Figure 2: Data source for the SortingPeople sample form template

    Considerations When Sorting Data
    Now we’ll look at how we implemented sorting functionality behind this form template. This is accomplished through C# code behind the form. While we could have opted for an easier XSL-based implementation to sorting data, it would not have been compatible with Forms Services. So we’re left to actually sorting the data. There are advantages as well as disadvantages to our approach. Sorting the data is preferred when you want to persist the sorting in the saved or submitted form. While the initial cost is much higher to sort the data in the data source instead of the view, there is much less processing that occurs on subsequent visits to that data because it will already be sorted. If your form template has multiple views, switching to and from a view that performs an XSL sort is very expensive. On the contrary, a sorted data source adds no additional processing requirements on view switches. A final reason why you may want to sort the data in the data source instead of the view: submitting sorted data to a database or Web service may be optimal (or even a requirement) for that backend system.

    Sorting Data with C# Form Code
    To best understand how we designed the code behind form template to support sorting, we’ll be talking about its C# form code and how it interacts with the main data source. Let’s start by looking at some of the supporting form code that will make it easier for us to implement the sort feature. The properties are used within the sort itself to read the options at the top of the view about how to sort the data. The methods are very useful helpers that we use throughout our sample code.

    /// <summary>

    /// Returns the "Sort By" Drop-Down value.

    /// The value returned by this property MUST match with an item within the Repeating Table.

    /// </summary>

    private string SortBySelection


        get { return GetValue("@my:SortBy").Replace(" ", string.Empty); }



    /// <summary>

    /// Does the user want the SortBy by number (true) or string (false)?

    /// </summary>

    private bool SortAsNumber




            return 0 == GetValue("@my:SortAs").CompareTo("number");




    /// <summary>

    /// Does the user want an ascending (asc) or descending (des) sort?

    /// </summary>

    private bool SortAscending




            return 0 == GetValue("@my:Order").CompareTo("asc");




    /// <summary>

    /// Helper to wrap an int within brackets.

    /// </summary>

    /// <param name="intToWrap"></param>

    /// <returns></returns>

    private string WrapAsIndexer(int intToWrap)

    { return WrapAsIndexer(intToWrap.ToString()); }


    /// <summary>

    /// Helper to wrap a string within brackets.

    /// </summary>

    /// <param name="strToWrap"></param>

    /// <returns></returns>

    private string WrapAsIndexer(string strToWrap)

    { return "[" + strToWrap + "]"; }


    /// <summary>

    /// Helper to get an XPathNavigator's value.

    /// </summary>

    /// <param name="xpath"></param>

    /// <returns></returns>

    private string GetValue(string xpath)


        return Root.SelectSingleNode(xpath, NamespaceManager).Value;



    /// <summary>

    /// Helper to set an XPathNavigator's value.

    /// </summary>

    /// <param name="xpath"></param>

    /// <param name="value"></param>

    private void SetValue(string xpath, string value)


        Root.SelectSingleNode(xpath, NamespaceManager).SetValue(value);



    /// <summary>

    /// Helper to get the document element of the main data source.

    /// </summary>

    private XPathNavigator Root


        get { return CreateNavigator().SelectSingleNode("/my:SortingPeople", NamespaceManager); }


    Next, let’s take a look at the code behind all of the Buttons in our form template. We created these event handlers through each Button’s properties dialog. Their implementations are quite trivial. You can see that adding additional sorting columns to the Repeating Table is a simple task. If you wanted to add a column that doesn’t need to be sorted, there’s nothing to do beyond adding the column in the Table!

    public void SortButton_Clicked(object sender, ClickedEventArgs e)





    public void LastNameSort_Clicked(object sender, ClickedEventArgs e)


        SetValue("@my:SortBy", "Last Name");




    public void FirstNameSort_Clicked(object sender, ClickedEventArgs e)


        SetValue("@my:SortBy", "First Name");




    public void AgeSort_Clicked(object sender, ClickedEventArgs e)


        SetValue("@my:SortBy", "Age");



    Now the million dollar question: what’s behind the SortList method? Let’s look and then we’ll explain how it works.

    /// <summary>

    /// Bubble sorts the list of people.

    /// </summary>

    private void SortList()


        string sortBy = SortBySelection;

        string itemsToSort = "my:People/my:Person";

        System.Globalization.CultureInfo currentThreadCulture =



        int numPeople = Root.Select(itemsToSort, NamespaceManager).Count;


        // basic bubble sort implementation

        for (int i = 1; i < numPeople; i++) // xpath is 1-based


            for (int j = i + 1; j <= numPeople; j++) // keep j ahead of i; we can index [numPeople]


                // swap (i,j) if necessary

                string iValue = GetValue(itemsToSort + WrapAsIndexer(i) + "/my:" + sortBy);

                string jValue = GetValue(itemsToSort + WrapAsIndexer(j) + "/my:" + sortBy);


                // Do we sort by number or string?

                if (SortAsNumber)


                    int iNum, jNum;

                    if (!Int32.TryParse(iValue, out iNum) || !Int32.TryParse(jValue, out jNum))


                        // Let InfoPath take care of the invalid datatype with its own validation, we'll keep sorting the rest




                    if ((SortAscending && iNum > jNum) || (!SortAscending && iNum < jNum))


                        Swap(itemsToSort + WrapAsIndexer(i), itemsToSort + WrapAsIndexer(j));



                else // SortAsString


                    if ((SortAscending && String.Compare(

                        iValue, jValue, true /*ignoreCase*/, currentThreadCulture) > 0)

                        || (!SortAscending && String.Compare(

                        iValue, jValue, true /*ignoreCase*/, currentThreadCulture) < 0))


                        Swap(itemsToSort + WrapAsIndexer(i), itemsToSort + WrapAsIndexer(j));



            } // end inner-for

        } // end outer-for


    Analyzing the C# Form Code
    Let’s break down what we’re doing in this SortList method. First we get the column to use for sorting, the XPath to the repeating group that we want to sort, and the culture of the thread so we respect the current locale when sorting. Next we get the number of people that we’ll be sorting. We need this number because we’ll use it for our bubble sort implementation.

    The two nested for-loops implement the bubble sort algorithm. We chose bubble sort because of its simplicity and for demonstrative purposes. (We’d recommend you use the most efficient sorting algorithm based on your requirements.) The variables i and j iterate through the people. We use the iValue and jValue variables to select the data pointed at by i and j to determine if a swap is necessary as part of the sort loop.

    Next, we have an if-else statement that checks if the sort is by string or by number. A sort by number will attempt to parse out 32-bit integer values from the iValue and jValue fields. If the parse fails for any reason, we skip this specific comparison and continue trying to sort the rest of the data. Once we have integers, we do a simple comparison and swap if needed. If we’re sorting by string instead of numerical value, we use the static .NET library String.Compare method to make a culture sensitive comparison. A swap is performed if it’s necessary. (Note that we could have combined some code in the SortList method to make it more compact. We left the structure of the code unoptimized for maximum readability.)

    The last bit of code we have not yet revealed is the Swap method. This method, as its name suggests, simply swaps the positions of two XPathNavigator objects as identified by their XPaths. (An XPathNavigator is a pointer into an XML tree of data. You can read more about the XPathNavigtor class on MSDN.)

    /// <summary>

    /// Swaps two XPathNavigators at xpath1 and xpath2.

    /// </summary>

    /// <param name="xpath1">First XPath.</param>

    /// <param name="xpath2">Second XPath.</param>

    private void Swap(string xpath1, string xpath2)


            XPathNavigator item1 = Root.SelectSingleNode(xpath1, NamespaceManager);

            XPathNavigator item2 = Root.SelectSingleNode(xpath2, NamespaceManager);


            // Make a copy of item1

            XPathNavigator item1Clone = item1.Clone();

            // Move item2 to item1


            // Make the original item2 be item1 that we cloned earlier



    Sorting Automatically
    One of the things you might ask is why we decided against sorting the data automatically. The most important reason is user experience and then followed by form responsiveness. Think about what would happen if the Repeating Table rows sorted themselves whenever data changed that required a sort. Say you were entering data into a new row. You start by typing a person’s last name and then either hit tab or click into the First Name field. If the form is sorting by the Last Name field, the row may have jumped to another location relative to the other rows in the Repeating Table! You would expect that you could fill in all of the data for a new row before it sorts itself. There are also other weird cases that automatic sorting would spoil. For example, you would not see a new row added within the middle of the Repeating Table. Why? As soon as you added it, it immediately jumped to the top (or bottom) of the Repeating Table as sorted data. Let’s consider for a moment why we didn’t automatically sort because of form responsiveness; for now let’s assume that we somehow worked out all of the kinks with the user model. Obviously the form will be less responsive in InfoPath, especially on a slow computer, with so much sorting. But the real problem is realized when filling out such an intense form template in a Web browser. Every time code runs while a form is filled out in a browser, the form data is posted back to the server for processing. Postbacks themselves can take several seconds or even minutes depending on many variables including the network connection speed as well as the client and server machines’ performance capabilities. As you can see, an automatically sorting form isn’t necessarily a better form.

    Hagen Green
    Software Design Engineer in Test

Page 5 of 12 (298 items) «34567»