Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

  • 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

    Working with VSTO 2008 Projects in InfoPath 2010

    • 8 Comments

    The InfoPath team is busy working on the next version of Office.  While we’re offline, we’d like to take the opportunity to tackle some of the questions that we get asked frequently by InfoPath users. 

     

     Today I’ll talk about how to migrate your InfoPath projects from Visual Studio Tools for Office 2005 or Visual Studio Tools for Office 2008 (VSTO) into InfoPath 2010 with Visual Studio Tools for Applications (VSTA).

     The decision to remove the ability to include InfoPath projects in professional developer solutions has been a controversial one, but is consistent with our overall message about SharePoint development – Create InfoPath forms with as little code as possible, and put the bulk of your code into middle tier services and workflows.

     That said, we frequently hear from users who invested in VSTO projects and need to know how to move those projects forward with InfoPath 2010 and Visual Studio 2010.  Here’s how.

     This walkthrough will demonstrate how to migrate InfoPath code projects from Visual Studio Tools for Office (VSTO), and into Visual Studio Tools for Applications (VSTA).

     First, ensure that VSTA is installed

     VSTA is an IDE included with InfoPath 2007 and InfoPath 2010.  The VSTA node is included in InfoPath 2010 setup.  Launch Office setup, choose to customize the install, and set Visual Studio Tools for Applications to ‘Run from my computer’.

      

    Next, migrate your project

    After installing VSTA, make a backup copy of your VSTO 2008 project that you will now proceed to migrate.

     Let’s walk through the conversion process of a VSTO 2008 project named “Hardware Order Form”. This project includes:

    1.       Custom classes used to create database connections and run queries. See DBConnection.cs.

    2.       External XML that are linked to the InfoPath data source. See Items.xml.

    3.       InfoPath form code. See FormCode.cs

    4.       References to non-default NETFW assemblies. See System.Windows.Forms and System.Data.

     Here is a screenshot of the Visual Studio project explorer to give an idea of the project structure:

    To migrate this project to VSTA

    1.       Launch Windows Explorer, and navigate to the InfoPath “manifest.xsf” for your project. This file is included in the “InfoPath Form Template” directory of your Visual Studio 2008 project by default.

    2.       You’ll see a list of files that directly correspond to the “InfoPath Form Template” directory shown in the VS Solution Explorer screenshot above. For example:

    3.       Right click “manifest.xsf”, and choose Design from the context menu

    4.       InfoPath 2010 Designer will launch.

    5.       Click the Code Editor button in the InfoPath 2010 Developer tab, and the browse dialog will appear

     

     

    6.       Click the Browse button, and navigate to the csproj file in the backup copy of your project. Select the csproj file and click ‘Open’.

     

    7.       VSTA will launch, and your project will be successfully migrated into InfoPath 2010 and VSTA.

     You can now work from within InfoPath 2010 and VSTA to code, build, and publish your solution.

  • Microsoft InfoPath 2010

    Cool Forms! Task Form

    • 8 Comments

    This week’s cool form was submitted by Sean Cantellay of Cantellay Consulting. The form allows the user to select a SharePoint task from the right and view it in the form on the page. The task has been broken up into four views and the tab buttons moves the user through the different views. The user can also Escalate the task to another SharePoint group by clicking the Escalate button and selecting the group.

    Click on images for larger pictures.

    ViewTwo

    ViewThree

    ViewFour

    EsclateView

    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

    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

    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

    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

    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

    Got suggestions?

    • 8 Comments
    One of the reasons we started this team blog was to get your comments (spurred by our tips and tricks), so it's exciting to see more folks chime in. Let me just take a moment to fan the flames…
     
    We're listening
    We're always open to feature requests to help us plan for future versions. And we're also interesting in blog post suggestions, which we'll try to post on quickly. If you have kudos, well of course they're always welcome. So leave a comment to let us know what you're thinking!
     
    Need support?
    If you need help solving a specific question, you're better off in the newsgroups, where both the product team and InfoPath MVPs are on watch and where there's a large archive of other like-minded questions. For more general issues or something you suspect is a bug, check out the support center. And for common tasks and basic overviews Office Online is your best bet.
     
    Thanks!
    - Ned
  • Microsoft InfoPath 2010

    Introducing the Multi-Select List Box

    • 8 Comments
    InfoPath 2007 introduces a new control, the multi-select list box, for cases when you want to allow users to select one or more items from the list of options. This list of options may be static, or may come from a data source. For example, you may use a multi-select list box to let the user pick the cities affected by the marketing campaign:
     
    You may also allow users to specify items not on the list by going to Multi-Select List Box Properties, and setting the option to allow users to enter custom values:
     
    Data source
    Multi-select list box stores data in a repeating field. Every time a user checks an option, a new instance of the repeating field is added; every time an option is unchecked, a field is deleted. This is just like the Bulleted List control.
     
    Let's analyze the data source at design time, and what goes into the XML when the form is filled out:
     
    Form Design
    Form Filling
    Data Source Pane
    User Input
    Persisted XML
    <my:campaign>
         <my:city>Chicago</my:city>
         <my:city>New York</my:city>
         <my:city>Boston</my:city>
    </my:campaign>
      
    Default Values
    To specify which (if any) items should be checked in the multi-select list box by default, click Default Values on the Tools menu. Using the marketing campaign example, if you don't want any option to be selected by default, uncheck the only "city" item:
     
     
    When you do this, you may see a design-time message that the "Control is bound to a missing field or group". You can safely ignore this message in this case since the point is to not have any checked by default.
     
    If, instead, you want several options to be checked by default, right-click on the city item, then click "Add another city below", and specify default values for both cities:
     
     
    Compatibility
    Multi-select list boxes are supported only in InfoPath 2007 client.
     
    - Alex Weinstein
    Program Manager
  • Microsoft InfoPath 2010

    Advanced server-side authentication for data connections, part 1

    • 8 Comments
    To tier three... and beyond!
     
    Real-world enterprise applications are seldom restricted to a single server.  Anyone who has created a nontrivial multi-tier application in a Windows environment has had to work around a fundamental limitation in NTLM authentication:  namely, that NTLM authentication tokens cannot be delegated past the second tier.
     
    Could you bounce off the wall and say that again?
     
    OK, in simpler terms:
    When you log onto your workstation, you present windows with primary evidence of your identity in the form of a username and a secret – usually a password, but sometimes a certificate or a biometric identifier such as a fingerprint.
     
    When you connect to a web application in a browser, your workstation contacts the web server and tells the server who you are.  The server trusts the workstation because it knows that the workstation has primary evidence of your identity, but the server has only second-hand evidence.
     
    When the web server connects to the data server, it passes your authentication token, but the data server won't accept it because the chain of trust is too long.  The data server has only third-hand evidence of your identity.  Bzzzzzzzzzt – thank you for playing!
     
    With InfoPath 2003, you never had to worry about these issues when designing your form.  You ran InfoPath on tier 1, and the database, Web service, or SharePoint site on tier 2 trusted your computer's first-hand evidence.  Now that you are designing forms that run in a web browser, you'll need to think about tier 3.
     
    There are a number of ways of dealing with tier 3 and beyond in forms services.  I'll start by briefly describing three simple techniques for noncritical applications, then I'll move on to enterprise-quality solutions, culminating in two technologies that are specific to Microsoft Office SharePoint Server.
     
    Keep in mind that for form templates that are not admin-approved and fully trusted, the connection settings need to be stored in a Universal Data Connection (UDC) file in a Data Connection Library in order to make a connection to another domain.
     
    Anonymous connections
    For trivial data connections, such as looking up a list of states to populate a drop-down list, you can simply allow anonymous users to access your data.  Removing the need to authorize the user means that it's no longer a problem that your identity can't be verified on tier 3.
     
    HTTP Basic Authentication
    In Basic authentication (or digest, which is a slightly more secure version of the same protocol), your browser prompts you to enter your username and a password, which are then passed in cleartext (or in digest form) to the web server.  The web server now has primary evidence of your identity, so the data server can trust it to tell it who you are.  You can set up IIS on your SharePoint server to use Basic authentication instead of Windows Integrated authentication.  While this is a quick way to do an end run around the tier 3 problem, it presents an awkward user experience on the intranet.   This is better suited to the extranet, where getting prompted for additional credentials is a more familiar experience. Don't forget to set up SSL so that your users' credentials are encrypted on the wire.  Otherwise, anybody monitoring your server traffic can read the passwords as they pass by.
     
    Embedded SQL credentials
    It's common practice in web applications to connect to a database using a SQL username and password embedded in the connection string.  Since this requires putting a password in cleartext in a configuration file, it is not considered a secure method of authentication.  By default, user form templates on the server are not allowed to use embedded SQL credentials.
     
    Kerberos
    Unlike NTLM authentication, a Kerberos authentication token, called a "ticket", can be independently verified at any point in an n-tier system and thus can be delegated indefinitely within the window of time that the ticket is valid.  For enterprises where Windows XP or better is the standard desktop and Windows Server 2003 is the standard server, Kerberos can replace NTLM as the standard authentication method in Active Directory.  This is the preferred method of overcoming the 2-tier restriction on token delegation when available.
     
    Constrained Delegation
    In constrained delegation, two services on two servers can be configured to allow a specific set of user accounts to be delegated from one service to the other without requiring independent verification of a password.  While this is considered a secure option, it is notoriously difficult to set up and maintain.
     
    Office Single Sign-on
    Office Single Sign-on (SSO) is a service on Microsoft Office SharePoint Server which was created to help applications on the server overcome authentication delegation issues.  At its heart, SSO is simply a database which stores encrypted username and password pairs.  An application running on the server can obtain a username and password associated with a known SSO application definition and can then use those credentials to log on to Windows and make a trusted connection to a data source. A form running on the server can use SSO to connect to external data by specifying an SSO application ID in the UDC file containing the connection settings.
     
    Web service proxy
    InfoPath Forms Services includes functionality to forward Web service requests from a form.  The web service request is made using the identity associated with the SharePoint web application.  In order to allow the web service to authorize access to the external data, the user's Windows username is passed in the SOAP header using a WS-
     
    Security UsernameToken
    In my next two installments, I'll describe in more detail how to use Office Single Sign-on and the Web service proxy to connect to enterprise data from your browser-enabled forms.
     
    In my next post we'll cover Single Sign On and write some code.
     
    - Nick
    Program Manager
  • Microsoft InfoPath 2010

    Open your rolodex from InfoPath using the Contact Selector

    • 8 Comments
    Speaking of Outlook integration, Microsoft Office 2007 includes a new control that enables you to choose one or more e-mail address from the address book.
     
    You can add this control to InfoPath’s list of custom controls by using the Add or Remove Custom Controls wizard like you would for any other ActiveX control.  When registering the control, you can choose most of the default options. However, you must choose "Field or Group (any data type)" in the "Specify Data Type Options" page of the wizard. If you don't choose this binding type, the control will be disabled when you try to fill out the form.
     
    When you insert this control in a form template, it looks like this:
     
     
    When you insert this control in design mode, only a group node is added to the data source. You must manually add additional fields in order for this control to work correctly. To determine the final data structure should be, open the properties dialog for the control and click on the "Items" tab. This tab lists the schema structure that is required.
     
    As I mentioned, you must manually add these fields to the data source. This can be quite painful if you want to use the control in a lot of form templates. However, here’s a little trick.  You can create a Template Part that contains only the data structure and no controls in the view. Now, when you need to use the Contact Selector, first insert the Template Part to create the data structure.  (This will insert an empty Section control into the view which you can then remove.)  Then, go to the data source, right-click on the group node that was inserted, and select Contact Selector from the More menu.
     
    Template Parts don't support ActiveX controls so you can't insert the Contact Selector into the template part which would make this even easier. However, using this empty template part that contains only the data structure is still easier than creating the structure from scratch each time.
     
    Scott Roberts
    Senior Development Lead
  • Microsoft InfoPath 2010

    Wizards (and we're not talking Harry Potter)

    • 8 Comments
    I just got back from some customer visits in Washington DC (governments tend to have a lot of forms…) and a common design pattern came up a few times: creating wizard-like forms. Since InfoPath provides all the built in tools to do this, without any fancy XPaths or code, I thought it would be fun to blog about here.
     
     
    Basic wizard
    Let's say you have a form that would be easier to fill out if folks could focus on one section at a time in a specific order. You can provide that experience by putting each section in its own view, and adding Back/Next buttons to navigate between them.
     
    Specifically:
    1. Open you form in design mode
    2. Open the Views task pane
    3. Click Add New View for each section in your form
    4. Copy and paste each section to its own view
    5. Open the Controls task pane
    6. Insert two Buttons
    7. Double click each button to open Button Properties
    8. Change the label for each button to "<< Back" or "Next >>"
    9. Click Rules to open the Rules dialog
    10. Click Add to add a rules
    11. Click Add Action to add an action
    12. For the Action, select Switch Views
    13. Select the view to switch to
    14. Copy and paste your button pairs to each view and update the rules to switch to different views.
     
    You can also provide this experience by adding Conditional Formatting to each section and hiding all sections that don't currently apply, but that can be cumbersome to design since the view can get so big, and I find it harder to manage the flow.
     
    Conditional Wizard
    InfoPath forms are dynamic, and wizard forms are no different. A common pattern is changing what data you collect based on what they selected earlier on. For example, it's tax time, so if I'm filling out a 1040 and select the option button to file as a single, I can skip the step that would ask me about dependents. You can get this in your form by adding a condition to the rule on your "Next" button, and adding a different rule for each view they could jump to.
     
     
    Some wizard pointers
    • Keep it simple. Try to minimize the number of controls on each page of the wizard. In fact, if you can ask for only one piece of information on a given page, your users will thank you. That said, if there is related data, keeping all of it on one page can be easier than having to skip back and forth.
    • Make it pretty. One of the benefits of a wizard is that you're not trying to cram all that data onto one page, so you have room to throw a graphic on the left in addition to a nice header. You can also wrap everything in a table to make sure the Next/Back buttons don't jump around. Eye candy for all!
    • Share where you are. If the wizard isn't conditional, leave the views on the View menu so people can quickly jump around if they want, and see how far they have to go. If the wizard is conditional so you don't want people jumping to the wrong pages, you can hide the views from the View menu using View Properties, but replace it with a chart at the top of each page to let them know how far they have to go. A simple text saying "25% complete" can go a long way.
    • Know when you're done. Presumably the last page of the wizard will submit the data. It's a nice touch to provide a summary of the data they've entered so far, and change the label on the "Next" button to "Finish" or even just "Submit".
     
     
    If you have any more tips on creating wizard forms, our team and the rest of the InfoPath community would love to hear them, so feel free to comment!
     
    Thanks,
    Ned
  • 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!)

  • Microsoft InfoPath 2010

    Auto-Fill from List Box

    • 8 Comments

    This came up on an internal mailing list:

    We have a secondary data source that holds a list of entries; part of the data in the list - a name field - is used to populate the items in a listbox in the view. When the user selects an item in the list, I want the rest of the data from that entry to be used to populate the form's main data source.

    Great scenario! It actually can be done with a combination of rules and filters (though I admit it’s not obvious), so you don’t have to write code for it.

     

    For this example, I will assume you have a form with:

    • A secondary data source with repeating items (for example, a list of people each with an ID, Name and Age)
    • A dropdown that lists the values in the data source (e.g. displays the name of each person and uses the ID as the value)
    • A set of nodes in your main data source that should be auto-populated when the dropdown changes (e.g. An age textbox that gets the age of the person selected in the dropdown)

    What you’ll need to do is create a rule on the dropdown. The rule will set the value in the textbox by filtering the corresponding value in the secondary data source down to one that matches the dropdown selection.

     

    Here’s how to do it:

    1. Double click the dropdown to open its Properties Dialog (it can be bound to a node in the main data source or in a secondary one, it doesn’t matter)
    2. Click the Rules button
    3. Click Add to add a rule
    4. Click Add Action
    5. For the Action, select Set a field’s Value
    6. For the Field, select the selectedAge node or whatever node you want to set automatically
    7. For the Value, click the Fx button
    8. In the Formula dialog, click Insert Field or Group
    9. In the Data Source dialog, select the secondary data source and then the age node or whatever node you want copy over
    10. Click the Filter button
    11. In the Filter dialog, set the filter to “secondary-data-source-ID is equal to main-data-source-ID”
    12. OK out of all dialogs, you’re done.

    Note that if your dropdown is inside a repeating section/table, then you will need to manually adjust the value in the formula dialog after step 11 to use the “current()” function so the filter works correctly.

     

  • Microsoft InfoPath 2010

    Using Relink When Moving a SharePoint Form Library to a New Site

    • 8 Comments

    When InfoPath form files are saved to a SharePoint Form Library, SharePoint creates hard-coded references to the form template in the team site where the forms are being saved.  If the SharePoint Form Library is moved to a new location, the references in the InfoPath form files will continue to point to the old location, even after they've been moved into the new Form Library. In order to fix up the references in the form files to point to the new form template location, you need to perform a Relink operation.

    Important   Before performing the Relink operation, make sure that the Windows SharePoint Services server you are working with has been updated with Windows SharePoint Services Service Pack 1. This service pack release fixes a bug that can cause data corruption when performing a Relink operation.

    Note   You cannot relink a form if the all data in the form has been digitally signed (the form template has been configured for signing by using the Enable digital signatures for the entire form option, or by using the Enable digital signatures for specific data in the form option with the Set of signable data specified using an XPath expression of "/"). This is because when a form has been signed using this configuration the link to the form template is treated as part of the form data, and relinking would invalidate the signature. You can relink a form that has only part of the data signed (the form template has been configured for signing by using the Enable digital signatures for specific data in the form option with the Set of signable data specified as a subset of the data). For more information on using digital signatures, see Digitally Signing Data in InfoPath 2003.

    Here are the steps for performing a Relink operation:

    1. Open the new form library.
    2. Click Modify Columns and Settings to the left of the view.
    3. Under General Settings, click Relink forms to this form library.
    4. In the view presented, select all of the forms that you want to relink.
    5. Click the Relink button.

    The references in all of the forms you selected in step 4 will now point to the current form library location.

    Note   It is also possible to update the references in the form files using the Processing Instruction Update Tool provided with the InfoPath 2003 Software Development Kit (SDK); however in most cases the using the procedure above is simpler.

  • Microsoft InfoPath 2010

    Filtering using the current() function

    • 7 Comments

    For some reason, the last week has been full of questions where the answer boils down to “use the current() function”.

     

    The current() function is an XSLT XPath function which returns the current node. You can read the full W3C Recommendation if you want the nitty-gritty details, but if you wanted to read the specification you’d probably have done that instead of reading this blog.

     

    You need this function in InfoPath if you’re trying to refer to data across repeating contexts. Some examples:

     

    ·        Within a repeating table row, you want to build cascading drop-downs

    ·        You want select or filter data from another context by data in the current row

    ·        You want one row in a repeating table to refer to data in the previous row

     

    These all come down to the same need – within an XPath expression, how do you say “this one”? That’s what current() is for. Whenever an XPath is being evaluated in a repeating context, current() returns the... well... current item.

     

    Scenario: Within a repeating table row, you want to build cascading drop-downs

     

    If your schema looked like this:

    • Root
      • Data
        • States
          • State (repeating)
        • Cities
          • City (repeating)
            • @state
      • Selection
        • SelectedState
        • SelectedCity

    And you wanted to have drop-downs bound to State and City which select from the appropriate list, you can build cascading drop-downs using filters. You’d end up with a filter on the list-box items that looked like this:

    /Root/Data/Cities/City[ @state = ../../../Selection/SelectedState ]

    (If you used the interactive condition builder, simply select “The expression” in the first drop-down to show the expression as an XPath.)

     

    Now let’s change the schema a bit to put the selections into a table – maybe with notes about each selection:

    • Root
      • Data
        • States
          • State (repeating)
        • Cities
          • City (repeating)
            • @state
      • Table
        • Row (repeating)
          • Selection
            • SelectedState
            • SelectedCity
          • Notes

    If you try this in a Repeating Table row (/Root/Table/Row) you’ll find that it doesn’t work as expected:

    /Root/Data/Cities/City[ @state = ../../../Table/Row/Selection/SelectedState ]

    The XPath /Root/Table/Row/Selection/SelectedState - which for practical purposes here is the same as ../../../Table/Row/Selection/SelectedState - actually returns all of the states in all of the rows, and in XPath the predicate a[b = c] returns all a's where any b equals any c. If you parse that explanation carefully, you'll see that you get far more results than you were expecting. In this example, you get a list of all cities from any of the selected states! What you need is a way to say “just the current Selection/SelectedState”.

     

    The fix then is to modify the XPath to read:

    /Root/Data/Cities/City[ @state = current()/Selection/SelectedState ]

    Scenario: You want select or filter data from another context by data in the current row

     

    This is actually just a simpler version of the previous case.

     

    Whereas a normal list of cities might be:

    /Root/Data/Cities/City

    And a static filtered list would be:

    /Root/Data/Cities/City[ @state = "WA" ]

    A dynamic filtered list would be:

    /Root/Data/Cities/City[ @state = /Root/Selection/SelectedState ]

    To pull the selection from the current table row the final XPath in the predicate needs to be made relative to the current row:

    /Root/Data/Cities/City[ @state = current()/Selection/SelectedState ]

    Scenario: You want one row in a repeating table to refer to data in the previous row

     

    This one is fun – let’s say you had a quiz (a list of true/false questions) and you wanted to disable controls in the current question until the previous question was answered. You’d use Conditional Formatting to disable the controls.

     

    If your schema looked something like this:

    • Root
      • Questions
        • Question (repeating)
          • QuestionText
          • AnswerText

    Then within each row you can use this expression to disable the controls:

    current()/preceding-sibling::Question/AnswerText = ""

    To enter this in the condition builder, select “The expression” in the first drop-down.

     

    (Note: In the example XPaths the namespace prefixes have been left out. Since InfoPath is extremely standards compliant - that is, nitpicky - when it comes to correct namespace usage you’ll need to include these.)

     

    [Edited 2004-09-13 @ 10:37 AM - one of the XPaths was incorrect]

  • Microsoft InfoPath 2010

    Extending the InfoPath control set with custom controls

    • 7 Comments
    InfoPath provides a rich and complete set of generic built-in controls in both 1.0 and SP-1, but there are some cases where there is a need for a control that is specific to your form or to your organization.  InfoPath SP-1 provides functionality to let users extend the set of controls available. Form developers can leverage currently existing ActiveX controls and use them within InfoPath. Also, following a few prescribed steps, software developers can write their own ActiveX controls to be used in InfoPath.

    InfoPath’s custom control support allows users to create controls for three different types of binding:

    Simple data type (string, numbers, etc)

    Controls that are written to bind to simple data types would allow a control to do custom processing on data before it gets put into the XML. The control can be designed to have UI that combines multiple simple controls (buttons, textboxes, checkboxes, etc…) to encapsulate them into one control. For example, multiple buttons can be combined with a textbox to make an in-document calculator control. Combining these all into one control will provide a simple way to re-use the same control in multiple forms.

    XML stream

    InfoPath SP-1 allows XML nodes to follow any schema. This allows form developers to work with industry standard XML Schemas. One example is a MathML control that could be written for InfoPath to save XML compliant with the MathML schema and display it in InfoPath form in a meaningful manner.

    IXMLDomNode

    For greater flexibility, InfoPath custom controls can be bound to an IXMLDomNode and any msxml operations can be performed directly on the XML tree.

    Deployment

    Custom controls need not be installed on every form users’ computer before loading the form. Controls can be packaged with your form solution so that on first open, the control will be registered and installed. Controls should be stored in a CAB files and able to self-register.

    Security

    Custom controls in InfoPath have a few security constraints to keep users safe. Firstly, all custom controls used within InfoPath require the IObjectSafety interface to be implemented and the control to be marked as Safe for Scripting and Safe for Initialization. Without these two flags, InfoPath will not load the form and will notify the user.

    In addition, for solution which have controls packaged in the form solution, it is necessary to sign the CAB files with a digital signature. When users open the form for the first time, they will be prompted on whether or not they will accept the control signed with that signature (similar to the ActiveX control dialogs you see in Windows 2k/XP).

    For detailed information on how to write a custom control for InfoPath, see Lab 06 in the MSDN InfoPath 2003 Training. (http://msdn.microsoft.com/library/en-us/odc_ip2003_tr/html/odc_INF_Lab_06.asp)

     

  • Microsoft InfoPath 2010

    Modifying InfoPath manifest.xsf file from script (1/5)

    • 7 Comments

    In this five part series we’ll show the reader how to programmatically manipulate InfoPath form templates.

    Part 1 of 5: The story

    There are many scenarios where you might need to modify an InfoPath form template (.XSN) after it’s already in use. Let’s say the URL of your Web Service changes.

    With InfoPath 2003 you need to change the URL manually:

    1. Open the form in design-mode (e.g. Right-click on the XSN and select Design).
    2. Extract files of the form template (XSN) into the temporary directory using File | Extract Form Files…, then close InfoPath
    3. Find manifest.xsf in the directory and open it in Notepad (or some other text editor).
    4. Find and replace all instances of existing URL with the new one.
    5. Save the modified manifest.xsf.
    6. Right-click the modified manifest.xsf, select Design, and finally use File | Save As... to save the form template as a XSN file.

    With InfoPath 2003 with Service Pack 1 (SP1), just open the form in Design mode, go to Tools menu, select Change Data Source, and in the wizard locate the new URL.

    But this isn’t (just) a sneaky way to convince you to download the SP1 Preview.

    What if you are responsible for maintaining hundreds of InfoPath forms which rely on the Web service? Even with SP1 this would be a lot of work. It would be nice to do it programmatically.

    The good news is that this is possible, even without SP1. The InfoPath XSN format is really a CAB file, and the files that make up the template are XML files which can easily be modified programmatically. You can pack/unpack a CAB file with help of extract.exe and makecab.exe utilities that are accessible for Windows users. Now the only things you need is to implement a small utility using script or managed code that will do the described above sequence automatically. Inside of the utility you should do the following:

    1. Unpack XSN file using extract.exe utility to the local temporary directory.
    2. Find manifest.xsf file and open it as a plain XML file.
    3. Replace the corresponding URLs using the XML DOM.
    4. Save the modified manifest.xsf.
    5. Pack all files into the XSN using makecab.exe utility.
    6. Clean up your temporary directory.

    If you write a wrapper around this process to enumerate all the form templates, your hundreds of forms will be updated just in a few minutes.

    Using this approach you can change not only URLs but SQL connection strings, files names, etc. If you want to learn more about the XSN format and the files that make it up, check out the InfoPath 2003 SDK. As always, be careful – save backup copies, test your code, test the templates before and after, etc.

    At the end of this discussion, the patient reader expects a good sample that supports the idea explained above. And we will definitely do it in the following parts 2-5 of the series.

    To be continued.

     

  • Microsoft InfoPath 2010

    Enabling Cuneiform Support in InfoPath 2003 SP1

    • 7 Comments

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

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

    In the list of Available Languages, select "Akkadian"

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

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

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

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

    (Picture of the InfoPath editor in Akkadian)

  • Microsoft InfoPath 2010

    Welcome to the InfoPath Team Blog

    • 7 Comments

    Welcome to the InfoPath team blog here at http://blogs.msdn.com/infopath/

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

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

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

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

  • Microsoft InfoPath 2010

    Calling code/script from a Rule

    • 7 Comments

    Rules are a quick way to add dynamic functionality to a form, so a lot of programmers choose to use rules even when they know how to write the code to do the same thing. However, sometimes after writing a complex set of rules they may realize that they need to do something rules doesn’t support, and we know they don’t want to rewrite all their rules in code just to add that one little bit.

    Alas, there’s no rules action type for “Call code”, but there is a roundabout way to call your code anyway.

    Let’s say you have the following function in your form template:

    VBScript
    Function Test(param)
      XDocument.UI.Alert("Param: " & param)
      Test = true
    End Function
    Jscript
    function Test(param) {
      XDocument.UI.Alert("Param: " + param);
      return true;
    }
    VB.Net
    Public Function Test(ByVal param As String) As Boolean
      thisXDocument.UI.Alert("Param: " & param)
      Test = True
    End Function
    C#
    public boolean Test(string param) {
      thisXDocument.UI.Alert("Param: " + param);
      return true;
    }

     

    You can call that function from the condition of a rule by using the xdExtension namespace.

    For example, here’s how to call the function from a rule when the form is opened:

    1. Click Form Options on the Tools menu.
    2. On the Open and Save tab, click Rules.
    3. Click Add, name the rule, and then click Set Condition.
    4. Select The expression in the first drop-down list, and then enter: xdExtension:Test(“foo”)
    5. If you want the function to be conditional, then put the condition before the function call with an AND clause. For example, to get if foo>bar, then Test(“foo”), use foo>bar and xdExtension:Test(“foo”). (This is possible because conditions are evaluated using short-circuit boolean evaluation. In other words, they are evaluated one clause at a time, and if the first clause determines the result, then the rest of the conditions are “short circuited” and don’t get executed.)
    6. The Rule dialog box requires at least one action, but if you don’t have any actions to run in that rule, you can click OK if you select the Stop processing rules when this rule finishes checkbox. To avoid actually stop processing rules, make your condition always return false. For example: xdExtension:Test(“foo”) and false (“false” here is actually looking for the node named “false” which doesn’t exist, so returns the empty set, which is translated to false(). You could just as easily use “foobar” or anything else.)

    Finally, extract your form files and add the following attribute to the manifest.xsf file’s xDocumentClass element:

    xmlns:xdExtension="http://schemas.microsoft.com/office/infopath/2003/xslt/extension"

  • Microsoft InfoPath 2010

    Advanced server-side authentication for data connections, part 3

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

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

    How to Integrate the .NET Framework SDK Documentation with VSTA

    • 7 Comments

    The .NET Framework 2.0 SDK documentation includes the Visual Basic and Visual C# language references, as well as the documentation for the .NET Framework classes. You can download and integrate this documentation into the Help viewer for the Visual Studio 2005 Tools for Applications (VSTA) integrated development environment (IDE) that ships with InfoPath 2007. After doing so, the NET Framework 2.0 SDK documentation will be available along with the "InfoPath Developer Reference for Managed Code Form Templates" documentation in VSTA IDE Help viewer for use offline.

     
     
     
     
    .NET Framework SDK Help in the VSTA Help Viewer
     
    Important   If you are running under Windows Vista with user account control, you must start InfoPath 2007 as an administrator before performing the following procedure. To do that, navigate to C:\Program Files\Microsoft Office\Office12, right-click INFOPATH.EXE, and then click Run as Administrator. If you are not running InfoPath as an administrator, you will be unable to complete the following procedure.
     

    To integrate the .NET Framework 2.0 SDK documentation with the VSTA IDE Help

    1. Start InfoPath 2007, and open or create a form template in design mode.
    2. On the Tools menu, click Programming, and then click Microsoft Visual Studio Tools for Applications.
    3. In VSTA, click Index on the Help menu.
    4. Search for Collection Manager, Help, to open the Visual Studio 2005 Tools for Applications Combined Help Collection Manager topic.
    5. Select the check box for the Microsoft .NET Framework 2.0 SDK Documentation in the list of available help collections at the bottom of the topic below Collections available for the default combined Help collection.
      If the .NET Framework 2.0 SDK documentation does not appear in the list of available Help collections, you must install the .NET Framework 2.0 SDK. To install the .NET Framework 2.0 SDK, see http://go.microsoft.com/fwlink?LinkId=9832&clcid.
    6. Click the Update Help Collection button.
     
    You will be asked to close all instances of the VSTA IDE and the Help viewer, Microsoft Document Explorer. When you restart VSTA, the.NET Framework 2.0 SDK documentation will be available in the Help viewer.
     
    - Mark Roberts, Programmer-writer
  • Microsoft InfoPath 2010

    New InfoPath content on the web

    • 7 Comments

    I wanted to take a moment to recognize the great work of the Microsoft writers and editors who have been cranking out InfoPath content over the last few months.  While we in the product team have clicked over into Office 14 mode, they have continued to serve customers by creating Office 2007 content – everything from video demos to highly technical developer content.  Here’s some of the content that has been released since RTM.  Thanks to Anneliese Wirth, Arsenio Locsin,  Amy Miller, Anthony Labriola,  Kelley Vice, Tonda Kiffin, David Longmuir, Roger Haight,  and Mark Roberts for getting this information into the documentosphere!

     

     

    November 2006:

    -          Demo: Convert a Word document into an InfoPath 2007 form template

    -          Demo: Use InfoPath e-mail forms to view data in Outlook 2007

    -          Demo: View the business logic in an InfoPath 2007 form template

     

    April 2007:

    -          Article: How to: Share InfoPath 2007 Template Parts and ActiveX Controls

    -          Article: Hosting the InfoPath 2007 Form Editing Environment in a Custom Web Form

     

    May 2007:

    Article: How to: Evaluate and approve a form template

    Article: Guidelines for Creating InfoPath 2007 Converters

     

    June/July 2007:

    -          Article: Working with XML Data Using the XPathNavigator Class in InfoPath 2007 Form Templates

    -          Article: Guidelines for using colors, fonts, and images in a form template

    -          Article: Converting InfoPath 2003 Managed Code to the New InfoPath 2007 Object Model

     

    In addition some content that has been missing from MSDN has been re-published:

     

    -          InfoPath 2003 SDK:   http://msdn2.microsoft.com/en-us/library/bb190871(office.11).aspx

    -          InfoPath 2003 technical articles: http://msdn2.microsoft.com/en-us/library/bb191012(office.11).aspx

     

    We also have some excellent articles written by David Gerhardt of 3Sharp

    -           Developing InfoPath 2007 Managed-Code Solutions.

    -          Pulling CRM Data into InfoPath 2007 Browser Forms 

     

    And finally, InfoPath MVP Ben Walters just posted a code sample which shows how to limit the contact selector control to  single selection:  http://msmvps.com/blogs/benwalters/archive/2007/07/13/contact-selector-the-good-and-the-bad.aspx

     

    Enjoy!

  • Microsoft InfoPath 2010

    Extended data validation for the Multiple-Selection List Box in InfoPath 2010

    • 7 Comments

    Hi, Frank Mueller from the InfoPath development team here. The Multiple-Selection List Box (MSLB) control was introduced in InfoPath 2007 to enable users to select multiple items from a list when filling out forms. In this post, I will explain the different ways you can restrict and validate the data entered using this control in InfoPath 2010. I will also cover some advanced tips and tricks.

    In this post:

    Data Validation

    Special behavior in SharePoint List Forms

    Removing Blank Default Values

    Example Usage:

    First let’s look at a scenario where you may want to use the MSLB control. Say, for example, you are building a form for customers to order your company’s products. To be able to more effectively spend the company’s marketing budget in the future, the marketing department would like to know how your customers found the company’s web site. So you’ve added a Multiple-Selection List Box to gather responses to that question.

    Multi-select list box

    Your customers can now select one or more options. If a customer heard about the web site through a channel that is not specified in the Multiple-Selection List Box control, he/she can select the last checkbox and just type in a custom response.

    Data validation

    The marketing department is pleased with the new order form, but many customers do not bother responding to the “How did you hear about us?” question. With InfoPath 2010, solving this problem is very easy.

    In InfoPath 2010, there are two main ways that form designers can restrict and validate the data entered using the MSLB control.

    1. Require that at least one item be selected (At least one selection required) (NEW in InfoPath 2010)
    2. Require that every selected item have a value (Cannot be blank)

    Multi-select list box Properties

    Require that at least one item be selected (At least one selection required) (NEW in InfoPath 2010)

    New in InfoPath 2010, we can now enforce that users select at least one non-blank item by setting the “At least one selection required” property. In most cases, this is the setting that you will want to use.

    When you preview the form, you will notice a red asterisk in the upper right corner of the control, indicating that a selection is required.

    Multi-select list box If you select a blank custom value, an asterisk will appear in the top right hand corner of the custom value text box.

    Multi-select list box All asterisks will disappear as soon as you select an option that is not blank, or you select the custom value text box and type in a value.

    Technical Details

    The new type of data validation is only applicable to repeating fields that are bound to Multiple-Selection List Box controls.

    When setting the property at the field-level (instead of on the control), you will notice that it’s called “Non-empty occurrence required”. This is because the field can be bound to a control other than the MSLB, in which case users do not make selections when using the control.

    You may set any repeating field to “Non-empty occurrence required”, but you will only see an effect when the field is bound to a Multiple-Selection List Box control. “Non-empty occurrence required” is not implemented as an XSD constraining facet, but rather as a special Validation Rule that is stored in the manifest.xsf of your form template. This has the benefit that you can set the data validation even if you are designing a form template based on a locked schema.

    Require that every selected item have a value (Cannot be blank)

    In most cases, the “At least one selection required” property will do you what you need to ensure that users enter the required data.
    In InfoPath 2010, we still support the legacy “Cannot be blank” property. When this property is set, it requires that every item that a user selects from the list has a value. It does not however require that users select an item in the first place.
    When you preview the form, you will notice a red asterisk, whenever you select the checkbox of the custom value text box. This indicates that if the user wants to select this option, a value has to be typed in the text box before the form can be submitted. Once you type some text in the custom value text box, the asterisk will disappear.

    Multi-select list box

    Technical Details

    When a field in an InfoPath form is set to “Cannot be blank”, a minLength constraining facet is applied to the XSD element, which requires that corresponding XML nodes contain at least one character.

    <xsd:element name="field1" type="my:requiredString"/>   
             <xsd:simpleType name="requiredString">
                      <xsd:restriction base="xsd:string">                           
                              <xsd:minLength value="1"/>
                     </xsd:restriction>
    </xsd:simpleType>

    This makes sense for text fields, when the form designer wants to ensure that the person filling out the form has to enter data into the field before it can be submitted for further processing.
          First Name
    The Multiple-Selection List Box control is bound to a repeating field in the form’s data source. When the user fills out the form and makes selections in the control, a new XML node is created for each selection made. If you mark the repeating field that the control is bound to as “Cannot be blank”, InfoPath will ensure that all options selected or entered through the custom value textbox are not blank. However, if no selections are made in the control, no XML nodes are created, and hence the constraining facet of the field is not violated, and the user is not forced to make a selection.


    When would I want to use “Cannot be blank” instead of “At least one selection required”?

    If you want to ensure that users do not select any item that does not have a value then the “Cannot be blank” property can be used.

    In the example below, both “At least one selection required” and “Cannot be blank” are set. The data is not valid because the custom selection is blank.

    Multi-select list box

    In the example below, only the “At least one selection required” is set. The data is valid because at least one non-blank item is selected.

    Multi-select list box

    Advanced Information:

    Special behavior in customized SharePoint list forms

    In a SharePoint list, when you mark a Choice column as required, it requires users to select at least 1 item and for all selected items to have values.

    SharePoint Column Settings

    Marking the field as required in SharePoint, has the same effect as setting both the “Cannot be blank” and “At least one selection required” properties in InfoPath.  For consistency with SharePoint, when customizing a SharePoint list form in InfoPath 2010, only one data validation option, “Cannot be blank” is available.

    Removing Blank Default values

    When designing the order form described above, InfoPath will by default insert a blank default value node for each repeating field. As you preview the form you will notice that the custom value text box at the bottom of the Multiple-Selection List Box control will be checked by default.

    Multi-select list box

    If you wish there to be no default selection at all in the control, you need to remove the default value node.

    1. Click on the File button
    2. Select Form Options under the Form Information tab
    3. Select the Advanced category in the Form Options dialog
    4. Click on the Edit Default Values … button
    5. Click on the pluses in front of the fields to expand the data source until you can see the repeating field that is bound to the Multiple-Selection List Box control
    6. Uncheck the checkbox in front of the repeating field

      Edit Default Values

    7. Click OK to close both opened dialogs
    When you preview your form now, you will notice that the custom value checkbox is not selected by default.

    Multi-select list box

    Frank Mueller
    InfoPath Developer

Page 4 of 12 (298 items) «23456»