Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

  • Microsoft InfoPath 2010

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

    • 10 Comments

    Part 2 – Postbacks and conditions that cause them

    Welcome to the second article in our series on optimizing the performance of browser-enabled forms designed with Microsoft Office InfoPath 2007. In our first article, we defined performance in terms of responsiveness. In this article, we’ll focus on postbacks, one of the most common causes of reduced performance

    Postbacks are probably the most important factor affecting form performance because the effect of other conditions is amplified with each postback. There are two significant aspects of postbacks which we’ll examine in this series. First, which form features cause postbacks? Those features are the subject of this article. Second, what kinds of postbacks are more expensive to process, thus imposing an additional burden on the performance and scalability of the form system? We’ll examine those factors in the next article.


    What is a postback?

    Certain form controls, actions, and features require the browser to communicate with the server during the form-filling session. This exchange of data during the session is called a postback, and usually occurs when a form feature needs to send data to the server for processing. After sending the postback request, the browser must then wait for a response before it can update and re-render the form with the new data. In the case of a full-page postback, the browser must stop rendering completely until the whole updated page is returned, blocking user interaction with the form until it has been re-rendered. Alternately, to improve the user experience in the browser, some features use a partial postback, where only a specific part of the form is updated. This allows the user to continue interacting with other parts of the form while the update happens in the background. In either case, however, unnecessary postbacks impose an additional load on both the browser and the server. If you can reduce or eliminate postbacks as you design, develop, and test your forms, you can improve the performance and scalability of your entire form system.


    Browser-enabled form handling compared with InfoPath client forms

    To better understand the effects of postbacks on performance, it is helpful to compare basic form handling of the InfoPath-rich client with InfoPath Forms Services and browser-enabled forms. Whether you are new to InfoPath, or you are familiar with rich client forms but new to InfoPath Forms Services and browser-enabled forms, understanding these basic differences will help you improve your form design and troubleshooting strategies.

    The major difference between the InfoPath-rich client and browser-enabled form systems is that the InfoPath client doesn’t need to communicate with the form server as frequently as the browser does. This is because the InfoPath client processes most forms locally on the user’s computer. In contrast, the browser form relies on the server for a variety of form processing operations, requiring more communication to exchange data between the browser and the form server. Communication in the form of postbacks is a fundamental feature that allows InfoPath to support browser-enabled forms on the Web, but postbacks also make browser forms more sensitive to performance issues.

    Let’s look at two form loading and editing scenarios that further illustrate the difference between form processing in the InfoPath client and browser-enabled form systems.

    In the InfoPath-rich client scenario, when the user opens the form from a SharePoint form library, InfoPath first determines that the form should be opened in the client rather than the browser. After the initial download of a copy of the requested form template, InfoPath opens and renders an instance of the form on the user’s computer for editing. The form instance in the client is an XML document that the client renders in HTML for display. As the user interacts with the form, the InfoPath client processes and renders changes, and might run some custom form code, all within the context of the client running on the user’s computer. Generally, the only time the client needs to connect back to the server is to make additional data connection requests to query from or submit to a data source, to save a partially completed form, or to submit the final form.

    In the case of the browser-enabled form, when InfoPath Forms Services receives an initial request for the form from the browser, the server starts a session for that user’s form-filling session, allocates server resources, and processes the browser-enabled form template to load an instance of the form XML for the session. In addition, if the form requires it, the server might load and run custom form code and load data from a data source. After this initial processing, the server assembles the JavaScript and HTML that represent the form instance to be downloaded to and rendered by the browser.

    Finally, the server sends the response through a Web Front End server over the network to the browser on the user’s computer, which renders the initial download into the form view that the user interacts with. As the user interacts with the form in the browser, some form processing happens in the browser, but more complex form elements and events require a postback to the server for processing.

    During the transmission and processing of the form data, the browser instance of the form must wait for a response and then re-render the updated form. In this communication cycle, each postback request and response set constitutes a roundtrip. Each roundtrip affects the performance and scalability of the form system in terms of throughput, responsiveness, and resource utilization. This impacts both the browser side and the server side, as well as the network.

    As you can see from these two scenarios, a form-filling session in the browser-enabled form system requires substantially more communication than a similar session in the InfoPath client. In addition, more of the browser-enabled form processing is concentrated on the server, especially when multiple form-filling sessions are being served. In contrast, with an InfoPath client form, the form processing is distributed to the user systems. Consequently, reducing the number and complexity of postbacks as you’re designing browser-enabled forms can substantially boost performance.


    Ten common causes of postbacks

    1. Complex calculations

      A calculation can cause a postback when there is a condition that cannot be evaluated in the browser and requires processing by the server. For example, if a calculation requires data that is not loaded in the DOM, then the browser must send a postback to the server and wait for the result. Another condition that will invoke a postback involves any calculation that is out of the context of the current node. For example, you could create an expression such as .\.\.\my:field1+. When the expression is invoked in the form, because it requires traversing up the tree several levels from the current node, it must be sent to the server for evaluation.

    2. Data adapters

      The function of a data adapter is to make a query connection to an external data source, such as an XML file, a database, a SharePoint list, or a Web service, so that a form can receive and be updated with some data from the data source. If a form invokes a data adapter when the form loads, the browser must wait for the data connection, increasing form load time. If the form invokes a data adapter after the form loads, a postback containing the query request is first sent to the form server, which executes the data connection request on behalf of the browser form, adding additional time to the roundtrip.

    3. Multiple binding: data bound to multiple controls

      Multiple binding happens when one piece of data in the form is bound to two or more controls in the same view. This is usually done so that the same data can be displayed in multiple places. For example, you might design a report with several sections to include a single non-repeating field, such as "Report Date", inside a repeating section so that the same date is displayed in each report section. If you design a form this way, then changing the "Report Date" field in one location will update it everywhere because it is multiply bound. Unfortunately, the cost of this multiple binding might be a roundtrip to the server if the binding is more complex than the browser can resolve. In this case, server analysis is required to reliably identify all the controls bound to the same piece of data. In addition, if something is both multiply bound and out of context, then user edits to form fields will always require roundtrips. Other form actions that will cause roundtrips to the server when there is multiple binding include insertion or removal of repeating tables and repeating or optional sections.

    4. Out-of-context binding

      Out-of-context binding describes a situation where a control inside a repeating or optional section is bound to a node that is in a different part of the XML data source tree, outside the group node that contains the repeating or optional section control. When an out-of-context situation occurs in a form, the correct binding may be too complex to determine within the browser. If either the validity or the kind of action—such as a calculation—cannot be determined in the browser, the out-of context binding will trigger a roundtrip to the server to resolve the binding.

      You are most likely to encounter this problem as you’re designing a form in the InfoPath Designer if you first insert a group or control, and then later decide to move that group or control into an optional section. To avoid creating an out-of-context binding, after you drag and drop the control into the optional section, in the data source pane, drag the node the control is bound to into the group for the new optional section. The group or control will then be bound to the correct context.

    5. View switching

      Multiple views are often used to present a specific view to a specific user audience in a workflow. Multiple views are also commonly used to improve the performance of a form; by careful grouping of related items and limiting the number of controls in each view you can improve the form loading and rendering performance compared to placing everything in a single view. However, each time the view is switched, there is a full postback to send the user’s changes to the server, get the new view, and reload it in the browser. If possible, try to group the items on a view so that any controls that might postback do so when the view is switched. Then only one postback occurs when switching the view. A good example of this is using a button to invoke a query connection that returns data for a list, an operation that requires a postback. If the view is also switched when the button is clicked, you improve the efficiency of the postback. Another benefit of this design is that it makes the view switch a user-invoked action, which improves the user’s perception of the form response. By coordinating the postback of controls in the view with a view switch, you not only improve the responsiveness of the form, but also reduce stress on the server and network by eliminating extra postbacks. When designing your form there is no formula for when to use multiple views, so you will need to balance your use of multiple views with the potential design and performance advantages and costs in your user scenarios.

    6. Conditional formatting

      Conditional formatting is commonly used to hide part of a form from view until some condition is met. However, conditional formatting expressions fire every time the form is rendered whether hidden or not. Additionally, all of the data, calculations, and expressions used by fields that are conditionally hidden are still downloaded and can cause extra performance overhead. Thus if anything else invokes a postback, your form will incur this additional overhead. Similarly, if the conditional formatting requires a postback, then there is a postback each time the form is rendered. Although the primary reason for using conditional formatting has more to do with your form design and presentation, there may also be a slight increase in the responsiveness of the form if it uses conditional formatting. This is possible because it can be slower to render something in the browser than to execute the conditional formatting. However, if you need to substantially limit the presentation, consider using multiple views instead of conditional formatting because multiple views generally perform better.

    7. Digital signatures

      For forms that are filled out in Internet Explorer, signing a form uses an ActiveX control that communicates with the server using out-of-band postbacks. The signature operation involves 3 main steps:

      1. Gather client-specific information to be used by the signature data
      2. Server preprocessing to prepare the stored XML document for signing
      3. Apply the final signature

      Each step causes a postback, the first and the last being relatively expensive. This is because the first postback sends, among other things, the data corresponding to the non-repudiation image to be stored in the signature. The last is a full postback that refreshes the browser with the new signed document that has been prepared on the server.

    8. Business logic event handling

      Normally, when a user changes the values of several controls in the browser form, the JavaScript form logic in the browser can optimize the changes, batching them together to avoid a postback for each change. This reduces the number of postbacks to one. However, this optimization is not possible if the form has code or other logic, such as rules or conditional formatting, that listens to data changes in parts of the XML DOM. For example, if a control is bound to a particular DOM element and a listener is present, changes in that control are immediately communicated to the server and the corresponding event handler invoked. The number of extra postbacks depends not only on the number of event handlers, but also on the XPath they use to listen to DOM events. This is because InfoPath XML events bubble. For example, if some form code has business logic with an event handler that listens to a node close to the root node, there will be relatively more postbacks. This is because any browser change affecting one of the descendants of that node will trigger a postback to the server. Consequently, if your form uses form code or any other construct that involves listening to changes, it is important for performance and scalability that you understand and carefully scope events to reduce unnecessary postbacks and server stress.

    9. Custom hosting pages and external page events

      If you are using advanced form techniques such as developing your own ASP.NET page to host the InfoPath Form control, then there are a couple of things you should be aware of. Submitting to a custom hosting page requires full page postback because the XmlFormView control resides on the server and it involves rebuilding the page controls by ASP.NET. In addition, when submitting the form, before the submit is finalized, data is sent back to the browser with a pending submit action added. This pending submit action must then be sent back to the server in another postback to actually complete the submission. If the page is hosted on a SharePoint site, it also must initialize the SharePoint page infrastructure as well. Also, if an XmlFormView control is hosted on a custom ASPX page and the page listens to events from the control, then every operation triggering an event in the XmlFormView control will require full page postback.

    10. Complex XPaths

      In some advanced form design scenarios, you might build your own complex custom expressions or calculations using the "Edit XPath (advanced)" option. Although most common expressions or calculations can run in the browser, those that require more complex XPaths to evaluate may need to postback to the server. The following complex XPath conditions will cause extra postbacks:

      • More than one possible context for a filter
      • Complex XPath that is not used as a filter
      • XPath where the user input  is not a filter
      • XPath filter or rule that references an element that is not in the current view
      • XPath filter that is position-based
      • XPath with inline functions
      • XPath that includes an unrecognized function
      • XPath that includes an extension function that is not supported by the browser
      • XPath has an inner expression
      • Expressions containing inner nodes

     

    What’s next?

    In our next article we’ll examine some of the conditions that make postbacks more expensive and that affect the performance and scalability of a server system running InfoPath Forms Services.

     

     

  • Microsoft InfoPath 2010

    Powerful Declarative Logic: Phone Number Parsing

    • 10 Comments

    When entering phone numbers in InfoPath, you can validate that it is a phone number easily enough (Data Validation->field1 “matches pattern” Phone number), but what do you do if the input does not match that pattern? Asking users to exactly enter the format “(000) 000-0000” may be a little constraining. Therefore, you may want a rule so that any combination of spaces, dashes, parenthesis and 10 digits will be reformatted nicely.  Below I will describe how to do this in a rule, although you could do the same in business logic. 

    For the rule’s action, you would want to use translate, substring and concat functions.  Logically, as your first action you would translate to remove all unwanted characters (spaces, dashes and parenthesis).  Then, as your second action substring and concat everything. 

    However, you cannot break it into two actions.  When the translate is executed, it changes the text field.  InfoPath immediately reruns the rule on that field (even before the rest of the actions are run from the first time).  For the second run of this rule, the conditions will all pass (as you would have a number like “0123456789” due to the translate that already happened), and the translate action would be run again.  This will happen repeatedly and causes a recursion error. 

    Therefore, you would need to do this all in one action (the rule will be rerun here, but the conditions will not pass since it will match the phone number pattern).

    On your text box, you will need:

    1. One condition with 3 parts:

    - Field “does not match pattern” phone number “and”

    - Without the “()- “ characters, it has length 10:
    “The expression” string-length(translate(., "()- ", "")) = 10 “and”

    - There are no characters other than digits and “()- “ characters
    “The expression” string-length(translate(translate(., "()- 0123456789", "")) = 0

    2. One action that removes (), - and spaces; takes substrings; and concatenates it all together at once:

    Set a field’s value “.” to concat("(",substring(translate(., "()-", ""), 1, 3), ")", substring(translate(., "()-", ""), 4, 3), "-", substring(translate(., "()-", ""), 7, 4)))

    And you're done! Note that this technique will work in InfoPath 2003 and 2007, and it is supported in browser-enabled form templates. Download the form template that has this trick implemented; make sure to save it to your desktop.

    Nicholas Lovell
    Software Design Engineer
    Alexei Levenkov
    Software Design Engineer

  • Microsoft InfoPath 2010

    Where do UDC files come from?

    • 10 Comments
    Where do UDC files come from? - I knew you’d ask. (For those of you who are wondering what a UDC file is, you should go read my post entitled "Making data connections work in browser forms.")
     
    There are a couple of ways to go about it. UDC files are just xml files with a specific namespace and schema, so once you have a few examples you can probably get around handily with notepad and cut and paste. However, we’ve made it easier than that with the new Convert functionality on the Manage Data Connections dialog. (For those intrepid souls who prefer the notepad route, a schema reference is being prepared for publication.)
     
    If you start out by designing your data connection the way you normally would, you can then use the Convert button to change the connection from settings in the form template to settings in a data connection file. (In fact, you can open any existing form template in InfoPath 2007 and convert existing data connections the same way.)
     
    To start with, make sure you have write permissions to a data connection library (henceforth "DCL") on the Microsoft Office SharePoint 2007 server you’re going to publish your form to. Then, using InfoPath 2007 Beta 2 or later, create your data connection or open a form template with an existing data connection. Make sure the connection is to a source supported by UDC. (E-mail connections, connections to a Microsoft Access database, or connections to an XML file in the form template cannot be converted to UDC connections.)
     
    Here’s the data connections dialog showing a few connections I threw together (you can get to this dialog off of the "tools" menu in InfoPath design mode):
     
     
    Click the Convert button and specify the path to your data connection library. If you click "Browse...", InfoPath will suggest a filename based on the name you gave the data connection when it was created.
     
     
    If you choose a data connection file that already exists, InfoPath will use the settings in the file you chose - don’t expect it to overwrite the original file with new settings. This could have unexpected results if the file that’s already in the library is a different connection type or returns data that does not conform to the schema your form template expects.
     
    For most cases, you want to leave the default connection link option. Choosing "centrally managed connection library" will cause InfoPath and Forms Services to look for the UDC file in the "Manage data connection files" library in SharePoint central admin. This is fine, but it means that you need to copy the file from the DCL where you created it to that location before you can use it. This presumes you have access to SharePoint Central Admin. See my last blog post entitled "Making data connections work in browser forms" for more information on this option.
     
    Once you click "OK" on this dialog, your UDC file will be created and saved to the location you specified, and the connection in the form template will be modified to retrieve settings from the UDC file rather than from the form template.
     
    NOTE: There’s a known issue in the Beta 2 release where you will see an "invalid URL" dialog at this point. This is benign and is no longer seen in the technical refresh.
     
    You now have a UDC file in your DCL, but you’re not quite done. By default, a DCL will require content approval before anyone other than the file’s owner can use the UDC file you uploaded. Unless the content approval requirement has been removed, a site administrator or someone else with the content approval right will need to set the file’s status to "approved."
     
    Adding Authentication
    InfoPath does not automatically configure server-only authentication options for you. However, when creating a UDC file, InfoPath automatically creates an authentication block within the UDC file that is preconfigured to use Office Single Sign-on. In order to use this authentication option, you’ll need to uncomment the authentication block within the file and add both the SSO application ID and the CredentialType. Most of the time, you’ll want to use the SSO credential to log onto Windows, for which you’ll need to specify "NTLM" as the CredentialType. The full list of possible credential types is as follows:
     
    Value
    Description
    Sql
    Credentials will be embedded in a database connection string for authentication against a SQL server.
    NTLM
    Credentials will be used to impersonate a Windows user
    Kerberos
    Credentials will be used to impersonate a Windows user using Kerberos
    CD
    The username will be used to impersonate a Windows user using Constrained delegation
    Basic
    Credentials will be used to perform HTTP Basic authentication
    Digest
    Credentials will be used to perform HTTP Digest authentication
     
    Reusing existing UDC files
    Once you’ve created your UDC file, you may want to use the same connection for other form templates. Among other things, this has the benefit of sharing settings for multiple forms in a common location. Changing the settings in the UDC file will cause all of the related forms to pick up the changes the next time they are used.
     
    There are several places in InfoPath where we expose the ability to re-use data connection settings exposed as UDC files in a data connection library. Here are a few examples:
     
     
     
     
    All of these entry points lead to this dialog:
     
     
    When you specify one or more SharePoint sites to search, this dialog allows you to browse available UDC files containing in DCLs on those sites. Based on the context, this dialog is filtered to show only applicable connections (for example, if you start from the "Design a form" dialog, this dialog will only show Web service and database connections).
     
    Once you’ve specified the UDC file to use, you may need to specify some properties for the connection that are not contained in the file (for example, for a SharePoint list connection, you’ll be asked to specify which columns to include in the data source), but otherwise, you’re done.
     
    - Nick Dallett
    Program Manager
  • Microsoft InfoPath 2010

    Improvements to Share Point integration - Property demotion

    • 10 Comments
    One of the new features in InfoPath 2007 when publishing to a SharePoint 2007 server is the ability to turn on property demotion.
     
    Property demotion is the ability to be able to modify fields that show up in SharePoint document libraries and cause those fields to be automatically updated in the underlying document (in this case InfoPath form).
     
    Where would you use demotion?
    Imagine you have a document library where you save your company assets as InfoPath forms. Let us say one of the fields in the library, is the current owner of this asset. When you need to bulk assign a bunch of assets from one person to another, wouldn't it be really easy if you can just update this field in a data grid view instead of opening each and every asset form and having to update it.
     
    Let us see how you can enable property demotion
    When you go through the publish wizard (File/Publish) pages for publishing to SharePoint, InfoPath will detect if the server is 2007 and if it finds that to be true, you will now be able to turn on property demotion for a field by selecting the check box as shown in the image below.
     
     
    Note that not all data types can be demoted and also fields that are within a repeating context cannot be demoted. For data types that don't allow demotion, the checkbox will automatically be disabled.
     
     
    Once you enable certain fields for demotion, they become available in SharePoint's data grid view to be edited. The data grid view can be accessed from SharePoint library using the Actions menu as shown below.
     
     
     
    Also since demotion happens on SharePoint side (when the field is edited), the form's business logic such as Data Validation, Rules, Formulas, Code and Script will not run at that time. So there may be situations when you do not want to turn on demotion for certain fields.
     
    Hope you find this helpful and look forward to see you turning on demotion.
     
    Thanks,
    Anand
    Lead Software Development Engineer
  • Microsoft InfoPath 2010

    Tabs

    • 10 Comments
    In my last post I covered how to make Wizard-like forms. This time I want to talk about another common practice for organizing all the fields in a form: grouping each set of fields onto a "tab" so the user can switch between the sets in whichever order they wish. While wizards are useful in forms with a clear flow, tabs are useful when the same form will be updated multiple times in different places.
     
    In Windows XP, tabs look like this (this screenshot's taken from InfoPath's View Properties dialog):
     
     
    InfoPath doesn't have a built-in Tab Control, but it's easy enough to build one using tables, buttons, and views, so let's do it!
     
    The basic idea
    Here's what to build:
    • Views for the contents of each tab
    • Table with shading to give the visual effect of tabs
    • Buttons for each tab with a rule that switches the view
     
    For example:
     
     
    Then when the user clicks "Details" they switch views to see this:
     
     
    How To, with tricks along the way
    1. Create all of your views (from the Views task pane)
      • Select the same color scheme for each view (use the Color Schemes task pane)
      • Use Background Color on the Format menu to make the background of each view the second color for the current color scheme (the second-darkest color at the top of the color picker)
    2. Insert a layout table (on the Insert menu, click Table)
      • Make it two rows high. The first row will be for the buttons, the second will be for the tab content.
      • Split the first row to make a cell for each view, plus one extra cell to take the remaining horizontal space.
    3. Insert a button into each cell (from the Controls task pane)
      • Add a rule to each button to switch to the corresponding view. Do this even for the current view's button.
      • Make the current "active" button Bold, so it stands out.
    4. Use borders and shading (on the Format menu)
      • Select all the buttons at once (hold down the Control key and click each one), then remove all borders and shading from the buttons (they're invisible except for their label!).
      • Select the entire table, then add borders inside and out using the first color in the color scheme (the darkest color).
      • Select the non-active cells and set their shading to the third lightest color of the color scheme.
      • Select the active cell and the content cell, and set their shading to white.
      • Select the active cell and remove the bottom border so it becomes connected to the content cell.
      • Select the right-most "extra" cell and remove the top and right border
    5. Copy the table to each view
      • Update the borders and shading to change the "active" cell for each view
      • Put all your fields for each tab in its content cell
     
    Getting fancy
    If the tabs above aren't pretty enough for your form, add some images inside a few more table cells around each button to provide rounded corners and other visual effects. It's more work, and requires some image editing, but with a little elbow grease you could get something as schmancy as this:
     
     
     
    Enjoy,
    Ned
  • Microsoft InfoPath 2010

    Download the Beta!

    • 10 Comments
    I'm super excited to announce Microsoft Office InfoPath 2007 Beta and Microsoft Office Forms Server 2007 Beta for browser-enabled forms, so you can install both of them today.
     
     
     
    After registering you'll get to select which products you want, which should include:
    • Microsoft® Office Professional Plus 2007 (includes InfoPath)
    • Microsoft® Office SharePoint® Server 2007 - Enterprise (includes Forms Services, which is also available standalone as Microsoft® Office Forms Server 2007. Both servers have 64-bit options.)
     
    All are available in English, French, Spanish, German, and Japanese, so tell your friends!
     
     
    Woohoo!
    - Ned and the whole exuberant InfoPath team
  • Microsoft InfoPath 2010

    InfoPath SP1 Released - how to install on systems with InfoPath SP1 Preview

    • 10 Comments

    You can now download and install the official InfoPath SP1.  It is part of the Office 2003 SP1 download.

    More details: http://office.microsoft.com/officeupdate/ .  English SP1 download is here.

    Please pay special attention to the following if you have installed the InfoPath 2003 SP1 Preview:

    InfoPath 2003 SP1 Preview and Office 2003 SP1

    If you previously installed the InfoPath 2003 SP1 Preview, you should uninstall the InfoPath 2003 SP1 Preview prior to installing Office 2003 SP1. You will need your original InfoPath 2003 product CD to upgrade to the final version of InfoPath 2003 SP1. For more information, see the Microsoft Knowledge Base article (873040): Information to consider before you apply Office 2003 Service Pack 1 to a computer that has the InfoPath 2003 Service Pack 1 Preview installed.

  • Microsoft InfoPath 2010

    Tips and Tricks for Making Form Filling Faster

    • 10 Comments

    The less time it takes to fill out your forms, the more time your users can spend on other tasks. Also, odds go up that form fillers will complete forms when they take less time to fill out. This blog post will give you a few tips for speeding up form filling and improving accuracy so your forms are completed faster.

    In this post we will cover

    1. Using defaults
    2. Using contextual defaults for bringing in the current day and user

    Setting up default values

    For questions where one answer is much more common than others, it can be useful to set up default starting values.  The value you choose will appear when the form is opened, but the form filler is still able to change it.

    You can set default values by selecting the control and clicking on the properties pane, and then choosing “Default Value”.

    Let’s say I had a sailboat rental form, and when boats are rented employees need to fill out who checked out the boat, when it was checked out, what type of boat it was, the boat #, and customer information.

     

    Because the sailboat rental place has mostly 24 foot boats, we can set the default Size to be 24 feet.   Now employees won’t have to fill this field out most of the time. To set a default value, select the control (the boat size dropdown), choose the Properties tab, and select Default Value. Type the default value in the box provided. You can set the defaults for text boxes, combo boxes, check boxes and many other controls this way.

     

    Contextual values

    When a boat is being checked out, we need to log the person who checked it out and the date. Most commonly, boats are checked out for today’s date. We want to set the default value of “checked out by” date to be today’s date.

    To set the checked out date to today, select the date control, go to the properties tab, and choose “default value”. Choose the function builder at the right .

    Choose the “Insert Function” button and pick the now() function from the Date and Time Category. Click “OK” until you return to the form.  Now, when users open the form today’s date will be automatically filled in.
    When using today() or now(), the form will update the date when you re-open it unless you uncheck the “Refresh value when formula is recalculated”. Make sure to uncheck this box.

     

    today() vs now()

    today() and now() can both be used to set the default value of a date picker. However, the type of form you have can affect which one you use.

         - Use today() when you have a date-only field.

         - Use now() when your field requires a date and time.

    In general, when using a SharePoint list form, use now(). When using a form library or filler-only form, use today(), unless you have changed the data format of the date field to date and time.

     

    Setting up the default user

    Setting the default value of the Person/Group picker is done through the fields task pane. Show the fields task pane by selecting “Show Fields” on the data tab and expand your Person/Group picker field (in my case, outBy). Click “Show advanced view” to see the detailed view. Right-click on the AccountId and choose properties.

     

    Under default value, choose the function builder  and type userName().
    Again, make sure that “Refresh value when formula is recalculated” is unchecked, so that this rule is only run once and not every time the form is opened. Click Ok.

     

    Repeat this process with the DisplayName (optional) to get the best experience. Now the people picker will default to the person who opens the form.
    When we load the form, the date, boat type, and checked out by fields are already filled out. With half of the fields completed, it will take employees less time to check out boats.

     

    Hopefully, these tips will help you set good defaults and your users will spend less time filling out forms!

    Kate Everitt

  • Microsoft InfoPath 2010

    InfoPath Quick Tip: Exporting InfoPath forms to Word

    • 9 Comments

    Want to export your InfoPath form view to a Microsoft Office Word document?

    The easiest way to do this is to export your InfoPath form to an MHT file using File | Export To | Web... while filling out your form. Then, just open the MHT file in Microsoft Office Word.  The Word document that you create based on the MHT file exported from InfoPath will look very similar to the InfoPath form itself.

  • Microsoft InfoPath 2010

    Protecting Sensitive Data

    • 9 Comments
    Frequently, we find developers using InfoPath as a platform for developing solutions that manipulate sensitive data, may it be financial data, patient records, or performance review forms. This article shares tips on protecting such data.
     
    First and foremost, you must know that an InfoPath form is a plain-text XML file. A malicious user can read it through Notepad or other text editor, circumventing any InfoPath authentication logic. So if a user has read access to an InfoPath XML form, anything stored in that XML file can be read. Information Rights Management in InfoPath 2007 allows storing encrypted XML; we'll talk more about it below.
     
    Also remember that an InfoPath form template (.xsn file) is just a CAB archive, containing plain-text files. These files store all client-side form logic. Information Rights Management allows you to encrypt form templates in InfoPath 2007, see more about it below.
     
    Like with any other client-server application development platform, you can never trust the logic that happens on the client. InfoPath uses the form template to store all form logic; if the user has access to the form template (and they must in order to be able to open any form based on that form template), they can create a hacked version of the template, circumventing any restrictions that the original form author put in place.
     
    This means that authentication and authorization performed on the client can't be trusted; calculations and data validation have to be re-done on the server. Here is an example of how this strategy can be realized for a simple record-keeping application:
     
    • Do not store sensitive data in the XML file; instead, store keys in the XML file, and perform queries on load that populate the rest of the data by using a database/web service. If the user is unauthorized (as determined by the server-side logic), return an empty dataset. You can even detect such condition on the client and show a friendly error message.
    • On submit, send the data to a web service and redo all non-schema validations on the server side. For example, if employees should not be able to submit expense reports above $100 without specifying an approver, have your web service process the dataset and verify that this condition is satisfied. 
     
    It is always a good idea to restrict access to a production form template by assigning read-only permissions to form users, write access to form maintenance staff, and no access to everyone else. This can be done by using permission features of the SharePoint Server or file shares. Even if you install form templates to the users' machines via a logon script, you can still control access to the .xsn file - provided the user is not running as an administrator, you can set their access to the template file to read-only.
     
    You may want to enable the protection feature for production form templates:
     
     
    However, remember that this protection feature is for recommendations only, it is not intended as a security mechanism. This will show the user a nice error message if they accidentally try to open the template in the Design mode, but won't defend the form template against a malicious user.
     
    Information Rights Management, or IRM, is a new feature for InfoPath 2007; some of you may already be familiar with the concepts from the other apps in the Office 2003 release. IRM allows the form author to protect both the form template and forms based on the template; IRM infrastructure must be in place in the organization to make this possible. Briefly, IRM is a way to encrypt both form templates and forms, allowing form author to specify who can access the template and suggest default rights for forms based on the template:
     
     
    Note that IRM is an InfoPath client-only feature, and it will not work in browser-enabled form templates.
     
    Alex Weinstein
    Program Manager
  • Microsoft InfoPath 2010

    One-to-Many Relationships on Database Connections

    • 9 Comments
    There have been a few questions about how the main database submit data connection works with related tables.  This is an FYI to clear up some of those issues, as I don't think this information ever made it public!
     
    At least one of the relationships for every pair of related tables must include the left-hand table's primary key (PK) (where A is the left-hand table in "A relates to B on A.ID, B.ID").  Without this stipulation, there may be many records in table A that map to one record in table B along the defined relationship.
     
    Note also that unique indexes and unique constraints allow nulls, so the primary key must be used in at least one relationship (they don't allow nulls).  Basically, InfoPath enumerates the records to be updated according to the primary key.  This way, the data inserted into the database is well-defined.
     
    What that boils down to is this:
    • Sufficient relationships:
      • PK --> Non-unique,  Unique, or PK
    • Insufficient relationships (assuming a sufficient relationship hasn't already been defined):
      • Non-Unique --> Non-unique,  Unique, or PK
      • Unique --> Non-unique,  Unique, or PK
     
     
    Once you've defined one sufficient relationship (as listed above), then you can define any other additional relationships that you want (they don't have to follow my rules listed above).
     
    - Forrest
    Software Development Engineer in Test
  • Microsoft InfoPath 2010

    MSDN WebCasts: InfoPath 2007

    • 9 Comments
    In April, the InfoPath team will present three MSDN WebCasts introducing the new features available in InfoPath 2007. These three presentations will provide a high-level overview of InfoPath 2007. In the future, we will offer more detailed presentations that dive down into individual features of InfoPath 2007.
     
    We hope you will join us for the first three InfoPath 2007 presentations. Here is more information about the first three talks including the schedule.
     
    New Features in Office InfoPath 2007
    Time: Tuesday, April 11, 2006 12:00 PM – 1:00 PM (PST)
    Presenter: Gray Knowlton, SR. Product Manager - Office
    Description: This webcast presents an overview of the new features in Microsoft Office InfoPath 2007 and InfoPath Forms Services. Join us to learn how you can use InfoPath 2007 to automate and extend business processes by utilizing XML and integration standards to connect electronic forms to virtually any application or system.
     
    Developing, Deploying, and Hosting Rich Client and Browser Forms for Microsoft Office InfoPath 2007
    Time: Tuesday, April 18, 2006 12:00 PM – 1:00 PM (PST)
    Presenter: Kalpita Deobhakta, Program Manager - InfoPath
    Description: Were you aware that you can design Microsoft Office InfoPath 2007 forms for both the rich client and the browser in a single step? This webcast presents the design-once process for InfoPath 2007, and covers debugging, deployment, and improving the performance and scalability of forms. Find out how to host the InfoPath rich client in other applications, and how to tightly integrate InfoPath 2007 forms into Web pages. We also discuss best practices for using the hosted form control to build powerful but easy-to-use solutions.
     
    Developing InfoPath Forms for Office InfoPath 2007
    Time: Monday, April 24, 2006 10:00 AM – 11:00 AM (PST)
    Presenter: Nima Mirzad, Program Manager - InfoPath
    Description: This webcast presents an overview of Microsoft Office InfoPath 2007 programmability features including the managed object model, template parts, and provisions for third-party hosting. We also discuss techniques for using Microsoft Visual Studio 2005 Tools for Applications (VSTA) and Microsoft Visual Studio 2005 Tools for the Microsoft Office System (VSTO) to develop Office InfoPath 2007 forms.
     
    Thanks,
    Scott Roberts
    Software Design Engineering Lead
    Microsoft Office InfoPath
  • Microsoft InfoPath 2010

    InfoPath and Yukon: The Details

    • 9 Comments

    In a recent post, I touched upon the reasons why you might want to go with SQL Server XML columns as the storage for your InfoPath forms. In this article, we'll talk about actually making it work.

    InfoPath's strength is working with XML data sources: web services. In the implementation below, we'll write a simple web service that will help us retrieve and submit the data to Yukon.

    Scenario

    Build a resume database for the HR department. We want to store highly structured resumes in a database. Highly structured here is the opposite of freeform: a resume in our scenario isn't a blob of text; we have the graduation date, employment dates, actual titles and other things parsed into data structures.

     

    Data Structure

    We will store candidate records as XML blobs in a Yukon XML column. Each resume will be stored as a separate record; each record will also have a primary key - a JobCandidateID - to simplify our development. We'll define only one table, called JobCandidate:

    Populate the table with a few Resume XML files that all satisfy the same schema. Store the schema somewhere where the web server can access it.

     

    Core Implementation in English: we'll write a web service as a middle tier between SQL Server 2005 and the InfoPath form. This web service will have two methods:

    1) GetCandidateRecord: given a JobCandidateID (an integer), return a DataSet (for our purposes, an XSD-typed XML blob) that contains the candidate record. Give me the job candidate ID, I'll give you his resume.

    2) UpdateCandidateRecord: take a JobCandidateID (an integer) and a Resume (an XML document), and update the resume of the candidate with that particular ID to the resume passed in as a second parameter. Nothing fancy, really.

     

    Core Implementation in C#

    I promised you two methods, here they are. First, GetCandidateRecord.

    [WebMethod]
    public DataSet GetCandidateRecord(int JobCandidateID)
    {
        DataSet result = null;

        using (SqlConnection conn = new SqlConnection(connString))
        {
            conn.Open();
            SqlCommand command = conn.CreateCommand();
            command.CommandText = @"
                SELECT Resume
                FROM "
    + tableName + @"
                WHERE JobCandidateID = @x"
    ;           
            command.Parameters.Add("@x", SqlDbType.Int);
            command.Parameters[0].Value = JobCandidateID;
            SqlDataReader reader = command.ExecuteReader();

            if (reader.Read())
            {
                DataSet ds = new DataSet();
                ds.ReadXmlSchema(@"C:\Inetpub\wwwroot\infopath_yukon\Resume.xsd");
                XmlDataDocument xd = new XmlDataDocument(ds);
                xd.Load(new StringReader((string)reader.GetValue(0)));
                result = xd.DataSet;
            }
            conn.Close();
            return result;
        }
    }

    Things are fairly straightforward here:

    - Open a SqlConnection using ASP.NET credentials (make sure the ASPNET user has read/write rights to the database).

    - Build a simple SELECT statement to return a resume. Recall that the resume is just an XML document stored as-is in the database.

    - Cast the resume dataset into a typed dataset by applying a schema stored somewhere on the web server. Oh, I forgot to tell you - you need a schema :-). Why? InfoPath form needs to know what to expect from the web service, and while InfoPath can infer the shape of the data from the instance, this method is very much error prone. For example, how can InfoPath know of a repeating structure if only one instance was present in a sample XML document? How about choice or optional structures? Because of all of these reasons, you need to provide a typed dataset through your web service.

    - Return the typed dataset for the Resume record.

     

    Next, let's look at UpdateCandidateRecord.

    [WebMethod]
    public void UpdateCandidateRecord(XmlDocument xml, int JobCandidateID)
    {
        using (SqlConnection conn = new SqlConnection(connString))
        {
            conn.Open();
            SqlCommand command = conn.CreateCommand();

            command.CommandText = @"
                UPDATE "
    + tableName + @"
                SET Resume = @x
                WHERE JobCandidateID = @y"
    ;
            command.Parameters.Add("@x", SqlDbType.Xml);
            command.Parameters[0].Value = xml.InnerXml.ToString();
            command.Parameters.Add("@y", SqlDbType.Int);
            command.Parameters[1].Value = JobCandidateID;
            command.ExecuteNonQuery();
            conn.Close();
        }
    }

    - Open a SqlConnection

    - Build a simple UPDATE statement to save the resume for a given candidate. Note that you must use SqlCommand Parameters: just concatenating the XML blob won't do.

    - Execute the UPDATE statement. Note that we are replacing the entire resume with the new one; no partial updates are done. This means that simultaneous editing of Resume records won't be possible.

     

    Basic Form Template

    Now that the web service is set up, we can easily build a form template based on it. The template may or may not be browser-enabled; the method described here works with both. Just launch InfoPath designer, and pick "start from web service" as your data source. Specify GetCandidateRecord as the "receive" piece of the web service, and UpdateCandidateRecord as the submit part.

    InfoPath will ask you for sample JobCandidateID values for the receive web service; since our database already has a few Resumes, we can type in the JobCandidateID for one of them. You may be wondering - wait, I thought InfoPath won't do the schema inference by example! It won't - the dataset returned by your web service will contain a schema (that's why we called DataSet.ReadXmlSchema() in GetCandidateRecord), and InfoPath will use that schema to build your data source tree.

    After you've gone through the initial data connection setup, you'll notice that your main data source tree is correctly populated with the data types from your schema. Complex structures should show up just fine - repeating, optional, choice structures, non-string datatypes, XSD validation... And the Submit button should be configured to save the modified Resumes back to SQL Server.


    FAQ

    1. Why do we have to use a custom web service, and not built-in Yukon web services?
    There are unfortunate technical limitations that currently require you to write a custom web service to work with SQL Server 2005 in a manner described above. The web service is, as you saw, very easy; we know that this is something that can be made better, and will consider addressing this in future versions of InfoPath and SQL Server.

    2. Why not XSD-typed XML columns?
    When InfoPath submits datasets to the web service, it adds dataset tracking information; while you can add optional attributes to your InfoPath-generated schema and upload it to Yukon, this would complicate maintenance quite a bit.

    3. What other resources are available on the topic?
    Be sure to check out this article by S.Y.M. Wong-A-Ton.

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Introduction to Sandboxed Solutions - Sort data in repeating tables using managed code

    • 9 Comments
    Hi. My name is Phil Newman and I'm a program manager on the InfoPath team. In this post, I'd like to introduce you to one of my favourite new features in InfoPath 2010 - Sandboxed Solutions. In InfoPath 2010, forms with code can now be published directly to SharePoint without requiring the farm administrator to approve and upload them! These forms run in a sandboxed environment which protects other resources on the SharePoint server from malicious code.

    In this short video demo, I show how you can add the ability to sort repeating tables in your forms using code.  I use picture buttons in the heading of the repeating table to trigger the code which sorts the table based on the values in the columns. 

    Get Microsoft Silverlight

    About the Code

    In a nutshell, the code puts the XML from the repeating table into an array, sorts the array using built-in .Net functionality, and then writes back into the XML to update the table.

    //Sorts a repeating table.  Takes the parent group node and the index of the column to sort by.

    private void SortTable(string xpathToSort, int columnToSortBy)

    {

    //get the values in an array

    string[][] ValuesToSort = GetRepeatingTableValues(xpathToSort);

    //sort the array

    Array.Sort(ValuesToSort, new StringArrayComparer(columnToSortBy));

    //write the values back to the xml

    SetRepeatingTableValues(xpathToSort, ValuesToSort);

    }

    //Takes an array of arrays and inserts it into a repeating table

    //Assumes that the array and table are the same size

    private void SetRepeatingTableValues(string xpathToSet, string[][] tableValues)

    {

    //Create a navigator on main node supplied in the parameters

    XPathNavigator mainGroup = this.CreateNavigator().SelectSingleNode(xpathToSet, this.NamespaceManager);

    //Clone the first child node of the main navigator and populate it with data

    XPathNodeIterator tableRows = mainGroup.SelectChildren(XPathNodeType.Element);

               

    //iterate through the existing XML and update the values from the sorted array

    for (int i = 0; i < tableValues.Length; i++)

    {

    tableRows.MoveNext();

    XPathNodeIterator thisRow = tableRows.Current.SelectChildren(XPathNodeType.Element);

    for (int j = 0; j < tableValues[0].Length; j++)

    {

    thisRow.MoveNext();

    thisRow.Current.InnerXml = tableValues[i][j];

    }

    }

    }

    //Returns an array of arrays of strings representing the values in a repeating table

    private string[][] GetRepeatingTableValues(string xpathToGet)

    {

    XPathNavigator myNav = this.CreateNavigator();

    int rows, cols;

    XPathNodeIterator tableNodes;

    //figure out the dimensions of the table

    tableNodes = myNav.SelectSingleNode(xpathToGet, this.NamespaceManager).SelectChildren(XPathNodeType.Element);

                rows = tableNodes.Count;

               

    //move to the first row to count the columns

    tableNodes.MoveNext();

    cols = tableNodes.Current.SelectChildren(XPathNodeType.Element).Count;

    //create an array to store the values

    string[][] tableValues = new string[rows][];

    //get all the rows in the table

    tableNodes = myNav.SelectSingleNode(xpathToGet, this.NamespaceManager).SelectChildren(XPathNodeType.Element);

    //iterate through the rows and write the inner xml of each element in each row to the array

    for (int i = 0; i < rows; i++)

    {

    tableNodes.MoveNext();

    XPathNodeIterator childNodes = tableNodes.Current.SelectChildren(XPathNodeType.Element);

    string[] rowValues = new string[cols];

    for (int j = 0; j < cols; j++)

    {

    childNodes.MoveNext();

    rowValues[j] = childNodes.Current.InnerXml;

    }

    tableValues[i] = rowValues;

    }

    return tableValues;

    }

    //Comparison implementation for array or arrays

    class StringArrayComparer : IComparer

    {

    private int iColumn;

    public StringArrayComparer(int iColumn)

    {

    this.iColumn = iColumn;

    }

    int IComparer.Compare(Object x, Object y)

    {

    string[] xAsString = (string[])x;

    string[] yAsString = (string[])y;

    return xAsString[iColumn].CompareTo(yAsString[iColumn]);

    }

    }

    Requirements for publishing your forms with code as Sandboxed solutions:

    • The Sandboxed code service need to be enabled on the farm
    • You must be a site collection administrator on the site collection you’re publishing to
    • Your form must be domain trust
    • Your form template must be an InfoPath 2010 template
    • InfoPath 2007 form code needs to be upgraded to InfoPath 2010 form code

    Complete sandboxed solution documentation is available here.  Note that InfoPath takes care of packaging and activating the solution, all you need to do is publish your form to a document library or as a site content type.

    I look forward to hearing your comments about this new feature. Let me know what you think!

    Phil

  • Microsoft InfoPath 2010

    Create tabbed navigation using picture button controls

    • 9 Comments

    In the 2nd installment of our "5 for Forms" video demo series, Charlie Han, a program manager intern on the InfoPath team shows how you can use our new picture button control to create tabs to more easily navigate your forms.


    Get Microsoft Silverlight

    (There are additional steps required to create tabs in display views. Click here to find out more.)

    Enjoy!

  • Microsoft InfoPath 2010

    Use Rules and Filters to Create Cascading Dropdowns in Forms

    • 9 Comments

    Hi, my name is Anson Hidajat and I’m a program manager on the InfoPath team. In this week's “5 for forms” video demo, I will show how you can use rules and filters to create cascading dropdown lists in a tennis tournament bracket application.

    Get Microsoft Silverlight

    Enjoy and please send us your feedback!

  • Microsoft InfoPath 2010

    Customize an External List Form in InfoPath 2010

    • 8 Comments

    In this week's “5 for forms” video demo, Trey Brumley, a software design engineer in test shows how you can use InfoPath to customize the form for an external list on SharePoint that connects to a SQL Employee database through Business Connectivity Services.

    Get Microsoft Silverlight
  • Microsoft InfoPath 2010

    Cool Forms! Weather Forecast Form

    • 8 Comments

    This week’s cool form displays your local weather forecast by using a REST Web Service data connection to pull in weather information from an online weather service. There are two views to the form, one minimal and one extended. The form contains linked picture controls that use rules to concatenate the Web service data and generate a URL pointing to images on the weather site. By hosting this form inside the InfoPath form Web part, you can display the latest weather forecast information on your SharePoint portal pages.

    Minimal View:

    weather_minimal

     

     

     

    Extended View:

    weather_extended 

    For more information about using REST Web Service data connections with InfoPath forms, see our earlier blog post http://blogs.msdn.com/infopath/archive/2010/02/11/add-a-dynamic-map-to-a-contact-form-using-rest-web-services.aspx.

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

    • 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

    Displaying Contextual Help in a Custom Task Pane

    • 8 Comments

    With all the wonderful features in the new Office apps, it's easy to get lost!  InfoPath is no exception, and when you make clever use of the new features, you'll want to make sure that users understand how your form is supposed to work.  Wouldn't it be great if you could display contextual help information as the user navigates to fields in your form.  With the "Context Changed" event, you can execute custom code when the user filling the form causes the context node to change.  This will fire when the user focuses a control bound to a different DOM node than the current context node.

     

    Files you'll need

    The solution we provide here uses some resource files.  Download the attached files to accomplish the scenario.

    1. "CustomTaskPaneHelp.htm" - The HTML file that will be displayed in the custom task pane.  We will manipulate this document at runtime from custom form code to display the contextually appropriate help information.  Just update the styles in this file to change the appearance of the contextual help in the custom taskpane.

    2. "Help Strings.xml" - This file is a basic xml file that contains mappings from local node names to the title and help contents for the node.  This file will be consulted to retrieve the help information to be displayed in the custom task pane.

    3. "CustomTaskPane.cs" - This helper class wraps the HtmlTaskPane object to access elements in the custom task pane.  This will be added to your VSTA project.

    4. "FormCode.cs" - This contains the code to integrate the custom taskpane into the form template.

    Note that this method works in InfoPath 2003 and 2007, but this tutorial will walk you through the steps in for InfoPath 2007 - the UI is slightly different in 2003, but you can still make it work. Since task panes are a rich-client only feature, this method is not supported in browser-enabled form templates.

     

    Construct your help resource file

    Assuming you've designed your form template already, you'll have a nicely populated data source, replete with variously named nodes.  Now add contextual help data for nodes in the main and secondary data sources:

    1. Open the "Help Strings.xml" file in notepad (or another text editor.)

    2. Add a "Help" element for the data source node:

    • Set the "nodeName" attribute's value to "<node prefix>:<Name in Data Source Pane>"
    • Set the "Title" element's value to the heading that you want to display for this node's contextual help.
    • Set the "Contents" element's value to the body of this node's contextual help.

    3. Repeat step 2 for all nodes for which you want to display contextual help so that you have something like this:

    <?xml version="1.0" encoding="utf-8" ?>
    <HelpStrings>
       <HelpString>
          <Help nodeName="my:TextField">
             <Title>Text Field</Title>
             <Contents>Help for my text field.</Contents>
          </Help>
          <Help nodeName="my:RichTextField">
             <Title>Rich Text Field</Title>
             <Contents>Help for my rich text field.</Contents>
          </Help>
       </HelpString>
    </HelpStrings>

     

    4. Save the file to a shared location

    NOTE:  If you want to be able to update this help data without having to re-deploy the form template, the shared location should be accessible to all users that will fill out the form.  If, on the other hand, you do not care about that, then you can just save the file locally and add it as a resource file to the form template.  See below…

     

    Add the data source that will provide your contextual help data

    Now that you're help strings are all set, we need to add a reference to the help strings so that the form template can access them.  We'll do this by adding a data connection to query the xml file from a shared location or resource file.

    1. Tools >> Data Connections >> Add

    2. Select Receive Data, then XML Document

    3. Specify the location of the help strings document (Help Strings.xml)

    • If, as noted above, you want to include the help strings as a resource file in the form template, just click "Next >". Including the file as a resource file guarantees that it will always be accessible to the form template, but the form template will have to be updated if you need to change the help strings.
    • If, on the other hand, you would like to access the help strings file from a shared network location or web server, then select "Access the data from the specified location" and then click "Next >". Accessing the file from a shared location may fail if the shared location is unavailable, and there may be some delay due to network traffic.

    4. Check the "Automatically retrieve data when form is opened" check box and click "Finish" / "Close".

     

    Enable the custom task pane in your form template

    Custom task panes are not enabled by default.  We'll specify that the custom task pane should be displayed, and its content should be rendered from the "CustomTaskPaneHelp.htm" file.

    1. Tools >> Form Options >> Programming

    2. Check the "Enable custom task pane" check box. Type a name for the custom task pane in the "Task pane name" field.

    3. Add the "CustomTaskPaneHelp.htm" file as a resource file.

    • Click Resource Files >> Add…
    • Browse to the "CustomTaskPaneHelp.htm" file and click Open / OK.

    4. Select "CustomTaskPaneHelp.htm" from the "Task pane location" drop-down list.

     

    Add the code to manage the context change and display the contextual help information

    1. Tools >> Programming >> Context Changed Event; this will create the VSTA project and insert the "Context Changed" event handler.

    2. Add the "CustomTaskPane.cs" file to your project

    • Right-click the top-level project node.
    • Click "Add" >> "Existing Item…"
    • Browse to the "CustomTaskPane.cs" file and click "Add".
    • IMPORTANT: Edit the Namespace of the "CustomTaskPane.cs" file to be the same as that of your form code file.

    3. Integrate the code in the attached "FormCode.cs" file into your VSTA project.  Make sure you copy the contents of the "FormEvents_ContextChanged" method, as well as the private properties and variables.

    4. Build and save your form template.

     

     

    Make the form template full trust

    1. Tools >> Form Options >> Security and Trust
    2. Uncheck the "Automatically determine security level" checkbox. Select the "Full Trust" radio button.
    3. Click "OK"
    4. Save and publish the form template. You will need to publish the form template as an installable form template (.msi) or digitally sign the template; detailed instructions are here.

    Now, when users fill out your form, contextual help will be displayed for each node as the user clicks on a control bound to it.  As long as you've included help information in the help strings file, you'll see the help information in your custom task pane!

    Forrest Dillaway
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    Implementing Roles in Browser Forms

    • 8 Comments

    What are Roles? Without going much in detail, InfoPath roles is a functionality where you can define user tags like "Sales", "Management" and utilize them in your form logic. This enables some very interesting scenarios in the forms space. For a detailed discussion on this topic, take a look at this MSDN lab. If you have worked with InfoPath 2003, you would notice that Roles have not changed much in 2007, and that they are not supported by InfoPath Forms Services. My focus will be in how we can enable role-related scenarios in browser forms.

    For the purpose of this article, lets borrow the scenario from the lab. - "The management team at Contoso Corporation reviews each of the Sales Report filled out by sales representatives. Because the management team is interested only in sales deals that exceed a certain amount of money, your department is asked to add an additional view to the sales form that shows only those deals"

     

    STEP 1: Find a way to store role-related data

    You can store information about which users belong to which grounps in an XML file, included as resource as a part of the XSN. Here's one way to organize this XML file:

     

    <?xml version="1.0" encoding="utf-8"?>
    <roles>
        <role>
            <name>Sales</name>
            <users>
                <username>john</username>
                <username>jane</username>
            </users>
        </role>
        <role>
            <name>Management</name>
            <users>
                <username>bill</username>
                <username>abby</username>
            </users>
        </role>
        <role></role>
    </roles>

    Create a data source pointing to this resource file and use this data source to make decisions in step 2.

    Variation: Roles and Users relationship might be stored in a database (say HR system). You would then create a secondary data source connecting to your HR System instead of the XML file mentioned above; everything else stays the same.

    STEP 2: Determine the role of the current user

    1. Add hidden fields to the main data source of your form. These will store:

    • Active Directory username (alias) of the currently logged on (let's call the field CurrentUser)
    • Role of the current user, as determined by our form logic (let's call the field CurrentRole)

    2. Set the detault value of CurrentUser to the username() function.

    3. Set "CurrentRole" value to

    name[username = CurrentUser]

     

    STEP 3: Use rules and CurrentRole

    To accomplish our scenario, we will create two views: one for "Sales", and one for "Management". Using Rules, you can switch to the appropriate view on load of the form:

    1. With the form template in design mode, on the Tools menu, click Form Options.
    2. Click the Open and Save tab, and then click Rules, and the following two rules:

    • If CurrentRole = "Sales", switch the view to the Sales view.
    • If CurrentRole = "Management", switch the view to the Management view.

    And that's it! You can use CurrentRole the same way you'd have used Roles in the InfoPath smart client. Note that this trick works on the smart client, too - so if you want to create a roles-based InfoPath application, this method will help.

    Pradeep Rasam
    Program Manager

  • Microsoft InfoPath 2010

    Behind the Scenes of Administrator-Approved Form Templates

    • 8 Comments

    If you’re a server administrator for Microsoft Office InfoPath Forms Services 2007, there may be a time when you’re tried to perform some action on a form template and received an error message that looks like the following:

    “Form template was deployed as part of the 9b518781-2fcd-40fe-a1f4-964b2cd4c0b8 feature”

    This feature name probably doesn’t mean a whole lot to you, and the error message could be a bit more actionable, right?  What the heck is this feature thing that the message refers to?  You might also have come across other IDs or other weird timing issues on a multiple server farm.
     

    Starting the Tour

    So, to shed some light on this, let’s go back-stage to see a little of what’s going on behind the scenes.  The stage is Windows SharePoint Servers Central Administration, where you will find 5 options in the Microsoft Office InfoPath Forms Services group on the Application Management landing page. This tour will mainly be concerned with the Upload Form Template page and a little bit with the Manage Form Templates page. 

    Let’s start at the Upload Form Template page, which is how a form template gets approved by the administrator.  Each new form template uploaded to the farm also adds a new FormTemplate object to the FormsService.FormTemplates which is the singleton FormTemplateCollection object for the farm’s administration object model.  This FormTemplate object allows the same manipulation that is available through the UI.  It also contains a lot of information used only internally to InfoPath Forms Services.  The most important internal property is the converted file, which is essentially a compiled version of the form template that can quickly render as a form template in the browser.

    When InfoPath form templates are uploaded to a server, the Windows SharePoint Services solution deployment and featurization infrastructures are being used to turn the form template into an administrator-approved form template..  Behind the simple click of the Upload button, InfoPath Forms Services creates a feature to deliver the form template (.xsn file).  The feature is then wrapped in a Windows SharePoint Services solutions package which is a .wsp file (just a renamed .cab file) that contains the feature and some other packaging information.


    The Solution Package

    This solution package is the means of deployment to all of the servers in a farm.  All Web front-end servers will have the form template propagated to their file systems, via the solution’s package.  So, there may be a delay in showing up on a multiple-server farm, hence the ellipsis in the “Installing…” status which remains until the form template is deployed to all machines in the farm.  These are propagated via the SPTimerv3 service which runs on each box and is scheduled to pick up jobs from servers running the central administration Web Application (where the Upload took place) and it uses the SPAdmin service to install the solution on the machine, via the administrator account.  So, InfoPath Forms Services deployment needs these services running on each machine, just like WSS solution deployment, because it’s actually the same thing.  Once deployment is completed, the form template is marked with “Ready” status.

    [Side Note: An implementation just like what we use for solution deployment is also available to you.  Our shipping documentation covers how to create features and solutions from scratch.  You might want to do this to bulk deploy many form templates at the same time, to indicated InfoPath form templates in other features or solutions, or to create a custom workflow that contains custom InfoPath form templates.  These custom-created solutions are still registered into the InfoPath Forms Services OM, but will be treated a little differently in IPFS, for instance, you cannot activate/deactivate/remove/upgrade these form templates through IPFS management, because that might invalidate the overall solutions that were constructed.  The whole features must be activated the same way that other custom features are activated (see Ready for Activation, below).]


    Ready For Activation

    The Ready status indicates that the form template can be used and is in normal operation.  The feature created, is a site collection-scoped feature (that’s SPSite-scoped in WSS OM-speak), which can be activated on an site collection like most other site collection-scoped features.  If you are a site collection owner, navigate to Site Settings, and see Site Collection Features under the Site Collection group heading.  Every form template that was administrator-approved through the upload page is available here along with the other site collection scoped features.

    You can also activate and deactivate features from the Manage Form Templates page in Central Administration.  This is exactly the same thing, and is provided as a courtesy for farm administrators who are also site collection owners.


    Behind the Scenes of Activation and Invocation

    An activated form template is added as an item in the Form Templates library at the root site of the site collection (SPSite.rootWeb) in the /formservertemplates path.  The form template is not actually present in the content database for the library, it is stored as a ghosted entry.  A user invoking the form template with the Microsoft Office InfoPath 2007 rich client is actually pulling the form template from the file system of the Web front-end server where it was placed by solution deployment.  Invoking the form template via the browser will pull the converted file from the FormTemplate object in the administration object model.

    The Form Templates library is special in a few ways.  The most important special aspect is that activated form templates cannot be unghosted.  This is to ensure that the converted file version and the on-disk version cannot be different, so that no matter what client you fill the form in, it’s the same form. 


    Be a Better IPFS Admin with this Knowledge

    Our hope is that this article will make our behavior more clear and expose a few tricks to help you be better Administrators.  Here are a few tricks in how to use that information to your advantage.

    Handle the error:  “Form template was deployed as part of the 9b518781-2fcd-40fe-a1f4-964b2cd4c0b8 feature”

    If you receive this, you most likely want to remove the form template and start over.  Here’s the action to take, and it’s only available from the command line:
    "%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\12\BIN\STSADM.EXE" -o uninstallfeature -filename 9b518781-2fcd-40fe-a1f4-964b2cd4c0b8\feature.xml

    Form template’s status never leaves “Upgrading…” or “Removing…” states

    These states seem to indicate that you're running a multiple-machine server farm, and on your server farm, you're running into some issues in propagating changes to all of the machines.  If you have not done so already, I highly recommend turning on the following services on each machine: SPAdmin, and SPTimerV3 You can do this by running:
                    net start SPTimerV3
                    net start SPAdmin
    On each machine.  Net start is a ensure semantic, so this will not inadvertently toggle or cause any damage if run on a machine where the service is already started.  Now that that's done, you can go on to correcting the problems that you have.

    From Central Administration, go to the Operations page, under the Global configuration group, click on Timer Job Status.  On that page, look for timer jobs that have the name in the following formatting.  If you filename is FOO.xsn, it will look like:
    Windows SharePoint Services Solution Deployment for "form-FOO.wsp"

    See if there was a failure.  If so, go back a page, and go to Timer Job Definitions.  Drill down in the timer job definition that you care about and you can perform the following:

    >> For the case of status stuck on “Uploading”:
    1.       Try to restart the job if that is available.
    2.       If restart is not available, delete the job, then attempt to upgrade again.

    >> For the case of status stuck on "Upgrading":
    1.       Try to restart the job if that is available.
    2.       If restart is not available, delete the job, then attempt to upgrade again.

    >> For the case of status stuck on "Removing":
    1.       Try to restart the job if that is available.
    2.       Else, Remove the job. (continue to step 3)
    3.       Then, go back to the Manage Form Templates and try again to Remove the form template.

    Ed Essey
    Program Manager
    Alexei Levenkov
    Software Design Engineer
  • Microsoft InfoPath 2010

    Creating Complex InfoPath Controls in C#

    • 8 Comments

    One of the problems with InfoPath controls is their limited availability. For example, there is no such control like the NumericUpDown control in WinForms. Or you may have a predefined complex UI, which you want use multiple times.

    In these circumstances, what we need is a mechanism for control extensibility. Today, InfoPath provides two different control extensibility mechanism: Template parts and ActiveX controls.

    Basically, template parts are predesigned InfoPath form templates, that can be imported into other templates. This mechanism provides a good way of reusing the same controls again and again, but on the dark side, you are still restricted with the control set of InfoPath.

    Other mechanism, which is extensibility via ActiveX controls lets you go beyond the control set of InfoPath and use whichever ActiveX control you want. In this blog, we will drill down into using a Windows control in InfoPath forms, and more importantly provide a way of binding data to these controls. This blog will give details of using WinForm controls that are registered for COM Interop, inside InfoPath forms. Two mainly used types for binding ActiveX controls to InfoPath data sources are 'Simple Binding', ‘Stream Binding’ and 'Node Binding'. In this article we will cover node binding. You can find more information about types of binding between ActiveX controls and InfoPath data source here:

    http://blogs.msdn.com/ajma/archive/2004/07/07/175568.aspx
    http://blogs.msdn.com/ajma/archive/2004/07/08/177512.aspx
    http://blogs.msdn.com/ajma/archive/2004/07/09/178857.aspx

     

    Simple Binding

    If your external control needs to be bound to a single field in InfoPath main data source, then you can use single binding between your ActiveX control and data source. An excellent simple binding example by InfoPath team can be found here: Creating an InfoPath Custom Control using C# and .NET. I highly recommend you to read this article first both to understand how to register our Windows Forms controls for Com Interop, and how simple binding is done for a primitively typed single field. Rest of the article will assume you read and applied the principles told in this article.

    Node Binding

    When binding to a single field or attribute is not enough, or you need your ActiveX controls to interact with data coming from different fields, node binding is the way to go. A classical example would be an ActiveX control capable of showing an Address type complex structure composed of Street, City, State and ZipCode fields.

    In this case, you need an Xml node in InfoPath form template as a data source that obeys the schema of Address object.

    InfoPath form

    We will design the data source of InfoPath first. Let's just write a schema file that corresponds to the structure of Address class. A simple schema file just including address data would be similar to this:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

          <xsd:element name="fields">

                <xsd:complexType>

                      <xsd:sequence>

                            <xsd:element ref="address" minOccurs="0"/>

                      </xsd:sequence>

                </xsd:complexType>

          </xsd:element>

          <xsd:element name="address">

                <xsd:complexType>

                      <xsd:sequence>

                            <xsd:element ref="street" minOccurs="0"/>

                            <xsd:element ref="city" minOccurs="0"/>

                            <xsd:element ref="state" minOccurs="0"/>

                            <xsd:element ref="zipCode" minOccurs="0"/>

                      </xsd:sequence>

                </xsd:complexType>

          </xsd:element>

          <xsd:element name="street" type="xsd:string"/>

          <xsd:element name="city" type="xsd:string"/>

          <xsd:element name="state" type="xsd:string"/>

          <xsd:element name="zipCode" type="xsd:integer"/>

    </xsd:schema>

    Start to design a new InfoPath form template from XmlSchema and use this schema as your source. InfoPath should parse the schema, and should create the data source entries in Data Sources tab in design task pane for you. At this point, let's create 4 text boxes that will display each of these fields. For the educational purposes of demo, do not drag and drop the whole address node onto the surface. Instead, drag and drop individual fields on to the design surface. This is because, after designing the ActiveX such that it is bound to whole DOM node, we will get a binding structure like this:

     

    UserControl

    Since we finished the main part of the form template, let's start to prepare the ActiveX object that we will use in the template. Assuming you read the article Creating an InfoPath Custom Control using C# and .NET, I will just touch the points not told there.

    Design the control
    Simply drag and drop four Labels and four TextBoxes on to the user control for each of the fields in Address type.

    Register for ComInterop

    As told in the article, we will need a Guid attribute for Visual Studio to register the control for Com Interop. What is not told in the article is, we need one more attribute to be able to register the control via Visual Studio: ComVisible. Although, UserControl class is donated with ComVisible(true) attribute in .Net framework, we have to state it explicitly one more time, because ComVisible attribute is created with AttributeUsage(…, Inherited = false), which prevents the value of the attribute to be inherited to children classes. So, our control should look similar to this for a successful registration:

    [Guid("08E623D3-BEAD-4bd3-8401-EFF51FD754CD")]

    [ComVisible(true)]

    public class ComplexUserControl : UserControl

    After building this code, a quick search through registry for Guid, will prove that class is really registered.

    Interfaces
    You should import the IObjectSafety interface exactly as told in the article. Before discussing IPropertyNotifySink, let's first take a look at the control interface, that will define the Value and Enabled property. In simple binding example, we had a primitive property in ICOMControl interface. Since we are no longer binding to a primitive field, we have to define a new interface.

    Let's define an IComplexControl interface similar to IComControl interface in the article. For Value property, we will use IXMLDOMNode type defined in Microsoft.Office.Interop.InfoPath.Xml.dll assembly that you will find in your Office 12 installation directory. This corresponds to a node in InfoPath main DOM data source. At the end, our interface should be similar to this:

    [InterfaceType(ComInterfaceType.InterfaceIsDual)]

    public interface IComplexCOMControl

    {

        [DispId(ComplexUserControl.DISPID_VALUE)]

        IXMLDOMNode Value { get; set; }

     

        [DispId(ComplexUserControl.DISPID_ENABLED)]

        bool Enabled { get; set; }

    }

    As stated in the article, Constants.DISPID_VALUE should be 0, and Constants.DISPID_ENABLED should be 1, in order for InfoPath to correctly communicate with our control.

    Now let's inspect IPropertyNotifySink interface. One of the main differences between Simple Binding and Node Binding is the type of the Value property. Simple binding deals with primitive types, whereas node binding deals directly with DOM. In simple binding a rough sequence of events would be like this:

          Property change in data source --> … -->Set Value property of ActiveX

    And the other way around:

          Property change in ActiveX --> Raise OnChanged -->InfoPath queries for Value property --> … -->Set Value property of ActiveX

    However, since InfoPath sends the whole DOM node as our Value property by reference, we don’t need to set an intermediary Value property. Instead we can directly change DOM values from DOM node reference. So we can safely ignore RaiseOnChanged and InfoPath queries for Value property steps. Since IPropertyNotifySink interface is used mainly for property change notification purposes will not implement it in this demo. If you care about Enabled property changes, you still have to implement this interface and notify InfoPath when Enabled property changes.

     

    Value property implementation

    When InfoPath first calls the setter of Value property after instantiating our control, it will pass in the IXMLDOMNode representing the main DOM of InfoPath. We have to keep this node in our control, in order to be able to change the data values corresponding to changes in UI.

    In the getter of the property, since we are not changing the reference of DOM node, it is safe to return this kept value.
    Whenever some field (or subfields in our group field)changes in DOM, InfoPath will call the setter of our Value property. In the setter, we should query the DOM according to XPaths of our fields, and then update the UI according to the values if necessary. At the end, our Value field should look like this:

    private IXMLDOMNode domNode = null;

    public IXMLDOMNode Value

    {

       get

       {

          return domNode;

       }

       set

       {

            if (domNode != null)

            {

                ChangeUI(streetTbx, domNode.selectSingleNode("/fields/address/street").text);

                ChangeUI(cityTbx, domNode.selectSingleNode("/fields/address/city").text);

                ChangeUI(stateTbx, domNode.selectSingleNode("/fields/address/state").text);

                ChangeUI(zipCodeTbx, domNode.selectSingleNode("/fields/address/zipCode").text);

            }

        }

    }

     

    private void ChangeUI(TextBox tbx, string text)

    {

       if (tbx.Text != text)

       {

        tbx.Text = text;

       }

    } 

    At this point we have completed the one direction of binding, originating from data source and going to UI. Now, let's handle the other way around, from UI to data source. In order to do this, we have to create a simple event handler that will catch change events in UI. Then register for all four text boxes' TextChanged events, such that each of them will be handled by this event handler. Code should look like this:

    public ComplexUserControl()

    {

        this.InitializeComponent();

     

        // Register for UI change events

        this.streetTbx.TextChanged += this.HandleChangesInUI;

        this.cityTbx.TextChanged += this.HandleChangesInUI;

        this.stateTbx.TextChanged += this.HandleChangesInUI;

        this.zipCodeTbx.TextChanged += this.HandleChangesInUI;

    }

     

    private void HandleChangesInUI(object sender, EventArgs e)

    {

        TextBox senderTbx = (TextBox)sender;

        if (senderTbx == this.streetTbx)

            this.ChangeDOM("/fields/address/street", this.streetTbx.Text);

        else if (senderTbx == this.cityTbx)

            this.ChangeDOM("/fields/address/city", this.cityTbx.Text);

        else if (senderTbx == this.stateTbx)

            this.ChangeDOM("/fields/address/state", this.stateTbx.Text);

        else if (senderTbx == this.zipCodeTbx)

            this.ChangeDOM("/fields/address/zipCode", this.zipCodeTbx.Text);

    }

     

    private void ChangeDOM(string xPath, string value)

    {

        if (domNode != null)

        {

            IXMLDOMNode singleNode = domNode.selectSingleNode(xPath);

            if (singleNode.text != value)

            {

                singleNode.text = value;

            }

        }

    }

    Integration

    In order to be able to use the ActiveX Control in the design of a form template, we have to make one final trick: Placing the .ict file that describes the control and its binding, to our controls directory. In order to add custom controls design task pane in InfoPath, generally you first go to the Controls tab, then click Add or Remove Custom Controls at the bottom of this tab, select to add a new ActiveX control, and finally select the ActiveX you want to add from the list of registered controls. If you have ever done this before, there should be a directory named

    C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\InfoPath\Controls

    In this directory there should be a .ict file for each of the ActiveX controls that you have done this operation for. We have to create a new .ict file for our control. If above directory does not exist, create it. Then create a file with name "{yourClassGUIDHere}.ict". This file should be in this format:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>

    <ict:control name="Complex C# Control, v1.0" xmlns:ict="http://schemas.microsoft.com/office/infopath/2003/ict" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xdSdl="http://schemas.microsoft.com/office/infopath/2003/xct" xmlns:ict2="ict2" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003">

          <ict:designTimeProperties>

          <ict:iconBitmap>Qk3uAAAAAAAAAHYAAAAoAAAAEAAAAA8AAAABAAQAAAAAAAAAAADEDgAAxA4AABAAAAAQAAAAAAAA/wAAgP8AgAD/AICA/4AAAP+AAID/gIAA/4CAgP/AwMD/AAD//wD/AP8A/////wAA//8A/////wD//////4iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiP//////////eIiIiIiIiI94RIRIRIiIj3hEhEhEiIiPeESESESIiI94RIRIRIiIj3iIiIiIiIiPd3d3d3d3d3eIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiA==</ict:iconBitmap>

          </ict:designTimeProperties>

          <ict:deployment>

                <ict:controlPackage classid="{yourClassGUIDHere}"/>

          </ict:deployment>

          <ict:shapes>

                <!--default shape-->

          </ict:shapes>

          <ict:schemaEditing>

                <ict:any/>

          </ict:schemaEditing>

         <ict:view>

               <ict:controlObject bindingProperty="Value" bindingType="xmlNode" enabledProperty="Enabled" enabledValue="true"/>

         </ict:view>

    </ict:control>

    Note the bolded text. You should place the correct GUID for your control, and note that we are actually specifying 'xmlNode' as bindingType. Rest of the file is almost standard except the iconBitmap part, which specifies the icon that will be displayed next to your control in design task pane.

    Since we have a ready control now, we can safely use it in our form template. Open the InfoPath form you have designed in design mode again. Go to Controls tab in design task pane. At the bottom, under Custom section, you should see the 'Complex C# Control, v1.0' with icon I have copied from Microsoft Forms Progress Bar control. Drag and drop this control to design surface. According to your security settings, it may ask you if you want to run ActiveX control. If so, press 'Yes' and continue. Since we have already defined a data source in the form, InfoPath will ask which field or group do we want our control to bind to. Choose address here. Now you should see the control on the surface, and its binding field is specified as /fields/address. Press Ctrl+Shift+B to preview the form. You should see the corresponding InfoPath TextBoxes and our UserControl's TextBoxes are synchronized, because they are bound to same data source fields.

    Now we have a functional complex WinForm UserControl, that we can display in an InfoPath form template, and even better, this UserControl is bound to InfoPath main DOM.

    Improving ActiveX Discrepancies

    If you played with the form a few minutes, you must have noticed that there is something weird going on. If you are changing the text value of InfoPath TextBoxes, you see a flicker in the UserControl before data is reflected to it. Similarly, if you change the value of a TextBox in your UserControl, you also see a flicker in the UserControl, and focus is continuously given to first TextBox added to UserControl.

    Main reason for this issue is, whenever a data field that is bound to your ActiveX is changed, InfoPath destroys your control and create a new one. This is mainly because InfoPath has to apply your view xsl to your data source to create the view you see on the display. Every time data source changes, InfoPath re-applies the xsl file and creates the view from scratch for controls that are bound to changed data fields. If you are debugging the form, you can easily see this by putting a breakpoint in the constructor of UserControl. Clearly, this leads us to write stateless controls, since each time the controls are destroyed, state is destroyed too. Or, as a second approach, we can take advantage of a helper interface, InfoPathControl interface, to save the state to some persistent storage just before destruction, and retrieve it after re-creation. Let's inspect how this approach works.

    InfoPathControl interface is defined in Microsoft.Office.Interop.InfoPath primary interop assembly. Add a reference to this assembly to your project and implement the interface on your UserControl. I advise you to read the explanation of all four methods of the interface, and how they are used in MSDN. Here, we will only concentrate on two of them, which are Init and SaveState methods.

    SaveState is called by InfoPath, just before the destruction of the older control, which makes it a perfect point to save the state to some storage. Init is called after creating the new control, which lets us to use it to retrieve the saved state and apply it to our control.

    Init method takes a parameter of type InfoPathControlSite. This interface gives us the main DOM node and XDocument of InfoPath form template, which basically enables us to access pretty much all of the object model of InfoPath. So, we don't have to wait for the setter of Value property anymore. We can cache the domNode here in Init method. We will also cache the XDocument for storing the state in, since we will need a persistent storage for our state while we are destroyed. In general, Init method body should be similar to this:

    private XDocumentClass xDocument = null;

    public void Init(InfoPathControlSite pControlSite)

    {

      this.domNode = pControlSite.Node;

      this.xDocument = (XDocumentClass)pControlSite.XDocument;

      this.RestoreState();

    }

    We will inspect RestoreState method after SaveState method.

    For simplicity, we will assume that we only want to keep which control has the focus in UserControl and give focus to that control after re-creation. Saving the name of the active control should be enough for state restoration. In reality in a control like this we should also keep the location of the cursor inside the TextBox as well as which TextBox is active.

    We said that we will use XDocument to save the state. This is because XDocument lives with the form template, so it is persistent during the lifetime of our control, and XDocument has a property bag that we can use for this purpose. We can update this property bag by calling SetNamedNodeProperty and querying it by calling GetNamedNodeProperty method on XDocument object. At the end, SaveState and RestoreState methods should be similar to this:

    public void SaveState()

    {

        if (this.xDocument != null)

        {

            this.xDocument.SetNamedNodeProperty(this.domNode, "ActiveControl", this.ActiveControl.Name);

        }

    }

     

    private void RestoreState()

    {

        if (this.xDocument != null)

        {

            Control activeControl = this.Controls[this.xDocument.GetNamedNodeProperty(domNode, "ActiveControl", this.Controls[0].Name)];

            if (activeControl != null)

            {

                activeControl.Focus();

            }

        }

    } 

    In the call to GetNamedNodeProperty in RestoreState method, third parameter is the default value, which will be returned back if specified property name can't be found in property bag. This will be the case when control is first created.

    Now, each time data source has changed, we save which control was active in UserControl before it is destroyed. Then InfoPath instantiates a new instance, we restore the state if there is any. Then InfoPath sets the Value property with updated fields.

    Saving the whole state in a WinForm control is a non-trivial task and maybe somewhat cumbersome. I'm optimistic about this re-creation of ActiveX controls will be optimized by InfoPath team in the next release.

    At the end, our code will look like this attached file.

    Deniz Demircioglu
    Software Design Engineer

  • Microsoft InfoPath 2010

    Data binding between Document Information Panel and Word document

    • 8 Comments
    The Document Information Panel is a Microsoft Office InfoPath 2007 form that is hosted and displayed in a Microsoft Office Word 2007, Microsoft Office Excel 2007 or Microsoft Office PowerPoint 2007 document. It enables users to view and edit properties of a document or a content type that is associated to a document management server.
    In Microsoft Office Word 2007, users can add properties from Document Information Panel as content controls to document surface. This is also known as data binding between Document Information Panel and Word document. Users can bind Document Properties, Server Content Type Properties or Custom Properties. Once the data is successfully bound, users can edit the properties from Word document surface.
    This article will demonstrate two ways to bind data from Document Information Panels to Word document surface.
    Method 1: Binding Document Properties or Server Content Type Properties to document surface
    1. Launch Office Word 2007
    2. File | Open to open any Document Information Panel document
    3. Place IP in the document where you want the property control to be
    4. Click Ribbon UI Insert | Quick Parts | Document Property
    5. Choose the property you want to add:

    You now have a content control in Word surface that binds data to Document Information Panel property. Please note that this method also works for Server Properties, but you need to save or associate the document with the Server document library first. Then you will see Server Properties in Quick Parts | Document Property list.
     
    Method 2: Binding Custom Properties to document surface
    For non-document or non-server related properties, which are defined as Custom Properties in this blog, there is no UI to bind these properties directly to document surface. Users need to use Word Object Model to do the data binding.
    Assume the Custom Document Information Panel has the following data structure:
    Here are the steps to bind the costCenterID property to Word document.
    1. Launch Microsoft Word 2007
    2. File | Open to open a document that contains this custom Document Information Panel
    3. Press Alt+F11 to launch Microsoft Visual Basic editor
    4. Press Ctrl+G to launch the Immediate window
    5. In the Immediate window, add a Text content control by triggering the following command:
    ActiveDocument.ContentControls.Add wdContentControlText
    1. Set up this content control XML mapping to costCenterID node by triggering the following command:
    ActiveDocument.ContentControls(1).XMLMapping.SetMapping "//*[local-name(.)='costCenterID']",, ActiveDocument.CustomXMLParts(4)
    Here the SetMapping function takes three arguments. First input is the XPath of the node you plan to do a mapping.  Second one is PrefixMapping input. Last one is Custom XML Part source where the node belongs to. In this case, costCenterID node lives in 4th custom XML part.
    1. Switch back to Word active document window. The content control should get set up.

    Now you have successfully set up properties mapping between Document Information Panel and Word document. When you edit the properties from Word document, the value is updated in the Document Information Panel automatically or vice versa.
    If you'd like to know more about the Document Information Panel, be sure to check out this webcast.
    Emily Ching
    Software Design Engineer in Test
  • Microsoft InfoPath 2010

    Digital Signatures: Layout Tricks

    • 8 Comments

    Folks frequently ask whether it is possible to customize the InfoPath user interface around digital signatures. Some want to show the signature at the very bottom of the form; others want to show signatures side-by-side; others want to disable form submissions when the document wasn't digitally signed. In this article, we'll look at different ways you can tweak the form design to make it happen.

    Trick 1: Display signature at the bottom of the view

    InfoPath lets you show digital signature UI ("click here to sign this form") under a signable section; however, this section doesn't have to include any controls! This means that you can have your signable section with controls at the top of the form, some extra content in the middle, and then another section bound to the same nodes in the data source without any controls in it.

    Your design view would look like this:

    Note how the signableGroup here is multiply bound; the first section has the "allow users to digitally sign this section" checkbox unchecked:

    The second one has it checked, which makes the "click here to sign this form" show up; this is how the end result looks at edit-time:

    Trick 2: Disallow Submit if form was not signed

    InfoPath digital signatures are appended to form XML, just like form data. For example, in the form above, nodes under signature1 will store the digital signature when the user adds it:

    Using this fact, we can enforce business rules in our form: for example, what if we don't want to allow form submissions for cases when form is not signed? Let's go to Tools | Submit Options and create two rules:

    1) Show must-sign warning:

        - condition: signatures2 node is blank (this will evaluate to true when no signature was added)

        - action: show a dialog box message "you must sign the form before submitting it"

        - check "stop processing rules when this rule finishes"

    2) Submit to main data source:

        - condition: always applies (unless the first rule fired - we wouldn't get to this execution point then)

        - actions: submit to main data source + show dialog box message "submission was successful"

    Trick 3: Show signatures side-by-side

    Challenge: make a form that has signatures side-by-side at the bottom; additionally, person 3 should only be able to add their signature if previous signer (person 2) already signed the document.

    We already know how to make the signatures appear at the bottom of view (trick 1); we also know how to determine if a signature was added to the document (trick 2). Let's put all of these tricks together into one powerful solution:

    - Create 3 different signed data blocks, one for each person that will be signing the form. Second data block needs to signing a superset of data that the first one signed, etc.  Your data source task pane will look like this: 

    - Place empty sections bound to the items that you want to sign in the columns of that table.
    - Use containing conditionally-formatted sections to show the signing UI only when necessary.

    The resulting layout will look like this:

    I'm attaching a sample form template that has this trick implemented (works in InfoPath 2003 or 2007; save the XSN to your computer before opening it).

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Date Calculations in InfoPath

    • 8 Comments

    The SP1 update of InfoPath 2003 added calculation support – the value of a node can be set to the result of an XPath expression. This makes it possible to avoid writing code (script or managed) in many InfoPath forms. Date calculations, however, still require knuckling down and writing old fashioned procedural code.

     

    InfoPath stores dates according to the W3C XML Schema standard, which in turn uses a variant of ISO 8601 dates. The XPath expression language, however, has no special support for date types – just strings, numbers, Booleans, node-sets and fragments. This means that while you can manipulate dates as strings – you can’t do calculations with them.

     

    Before we dive into some sample code, though, a few notes:

     

    You can do date comparisons with XPath! The date format is “yyyy-mm-dd” – always 4-2-2 – which means you can do lexical (“string”) comparisons on two dates and determine ordering and equality.

     

    As a guiding rule, you should be as paranoid with date calculations as you are with financial calculations. Identify and test your edge cases thoroughly, and make sure your code matches cultural interpretations, not code convenience. For example, if you compare two dates the context and desired result matters. The relationship between a duration in days and an age in years is not simply 1/365 (or 1/365.25, or … ) – the convention for age in most cultures is “has the person had a birthday yet?” so you’d better make sure the code matches. Who wants to miss their birthday?

     

    A good rule of software development is that if you have to think too much about a problem you’re writing too much code, and the more code you write the more likely you are to have bugs. So the moral of this story is: make someone else do all the work.

     

    The general pattern for dealing with date calculations in InfoPath is to use an existing library. The two handy libraries for this are the Windows Scripting engine and the .NET Framework. Since we have a lot of script examples on this blog let’s use .NET this time.

     

    The .NET Framework has a DateTime struct type and if you look in MSDN you’ll find it has plenty of methods and operator overloads for doing calculations such as adding days and computing TimeSpans. Looks good – I bet the .NET people know what they’re doing.

     

    So basically we just want to convert an XML date into a DateTime, do some stuff with it, then convert back.

     

    Here are the functions you need:

     

           private static DateTime Iso8601ToDate( string iso8601Date )

           {

                  if( iso8601Date == null )

                         throw new ArgumentNullException( "iso8601Date" );

     

                  return DateTime.ParseExact( iso8601Date, "yyyy-MM-dd", null );

           }

     

           private static string DateToIso8601( DateTime dateTime )

           {

                  return dateTime.ToString( "yyyy-MM-dd" );

           }

     

    Wow – after that preamble I bet that was a bit of a let down!

     

    Now let’s use it. I built a simple calculation form that looks like this:

     

    Date Calculation Form Screenshot

     

    The button handlers look like this:

     

           [InfoPathEventHandler(MatchPath="date1_add1", EventType=InfoPathEventType.OnClick)]

           public void date1_add1_OnClick(DocActionEvent e)

           {

                  IXMLDOMNode dateNode = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Date1" );

     

                  try

                  {

                         DateTime dt = Iso8601ToDate( dateNode.text );

                         dt = dt.AddDays( 1 );

                         dateNode.text = DateToIso8601( dt );

                  }

                  catch( FormatException ) {}

           }

     

    Then I added OnAfterChange handlers for the date fields which call a sync method:

     

           [InfoPathEventHandler(MatchPath="/my:myFields/my:Date2", EventType=InfoPathEventType.OnAfterChange)]

           public void Date2_OnAfterChange(DataDOMEvent e)

           {

                  if (e.IsUndoRedo)

                         return;

     

                  SyncDifference();

           }

     

           private void SyncDifference()

           {

                  IXMLDOMNode date1Node = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Date1" );

                  IXMLDOMNode date2Node = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Date2" );

                  IXMLDOMNode diffNode  = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Difference" );

                  IXMLDOMNode ageNode   = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Age" );

     

                  if( date1Node != null && date2Node != null && diffNode != null )

                  {

                         try

                         {

                               DateTime dt1 = Iso8601ToDate( date1Node.text );

                               DateTime dt2 = Iso8601ToDate( date2Node.text );

     

                               TimeSpan ts = dt2 - dt1;

                               diffNode.text = ts.Days.ToString();

                         }

                         catch( FormatException ) {}

                  }

           }

     

    You might notice that this is computing the difference in days. The TimeSpan structure represents an interval of time, and days are the maximum granularity that a pure duration can have – month and year durations require a fixed point in time to calculate from;  even weeks can be ambiguous – is that whole weeks or calendar-weeks-spanned? And whose calendar in the first place?

     

    So how do you go from two DateTime structures to an age? The old fashioned way – “have I had a birthday yet this year?”

     

           int ageInYears = dt2.Year - dt1.Year;

           if( ( dt2.Month < dt1.Month ) ||

               ( dt2.Month == dt1.Month && dt2.Day < dt1.Day ) )

           {

                  ageInYears--;

           }

           ageNode.text = ageInYears.ToString();

     

    Time calculations are even more fun. No-one mention leap seconds and we’ll get by just fine.

     

    (Update 1/25/05 @ 11:30 AM PST - having a problem uploading the screenshot to our images site. We'll fix that ASAP.)

    (Update 1/25/05 @ 11:50 AM PST - Fixed!)

Page 3 of 12 (298 items) 12345»