October 2006 - Posts - Antonio Gaetani
in

InfoPath Dev

Antonio Gaetani

October 2006 - Posts

  • Dynamically Alter the Choices of a List Control

    Have you ever found yourself wanting to bind the same control to different nodes? One solution to achieve the desired behavior is to create two controls with separate bindings and conditional visibility to hide and show them. This approach doesn't work well for drop-down lists when you have numerous choices because it creates too many permutations of drop-down lists. Instead you can use the xdExtension prefix with code-behind to update the values. This article demonstrates how to use xdExtension to dynamically alter the choices in a list control.

    Design the schema:

    To create a sample form to demonstrate this technique, we'll need a sample schema. Copy and paste the the schema below into a text editor, and then save the file as FormSchema.xsd.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <xsd:schema targetNamespace="http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-10-31T03:54:57" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2006-10-31T03:54:57" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="Sample">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="TextField" type="xsd:string"/>
                <xsd:element name="Set1" minOccurs="0" maxOccurs="unbounded">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="Set1Item" type="xsd:string"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
                <xsd:element name="Set2" minOccurs="0" maxOccurs="unbounded">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="Set2Item" type="xsd:string"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
                <xsd:element name="SelectedDataSource" type="xsd:string"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    </xsd:schema>

    Create the sample form:

    1. Launch InfoPath.
    2. Click Design A Form Template, and then click New From XML Document Or Schema.
    3. In the Data Source Wizard, click Browse, locate and select the FormSchema.xsd file, click Open, and then click Next.
    4. Select No for the question about whether to add another XML Schema, and then click Finish.

    Add controls to the form:

    1. Open the Data Source Task Pane
    2. Right-click TextField, and then select Drop-Down List Box.
    3. Right-click SelectedDataSource, and then select Drop-Down List Box.
    4. Right-click Set1, and then select Repeating Table.
    5. Right-click Set2, and then select Repeating Table.

    You can add values to the Set1 and Set2 tables to test the form.
     
    To switch between data sources, we will use the SelectedDataSource drop-down list. You will have to manually add two entries (see picture below), one with the value 1 and display name Set1, and another with the value 2 and display name Set2.

    Establish the set of default values for the drop-down list:

    1. Right-click the TextField drop-down list box, and then choose Drop-Down List Box Properties.
    2. Select Look Up Values In The Form's Data Source.
    3. Click the Select XPath button to the right of the Entries field.
    4. Select Sample/Set1/Set1Item, and then click OK. Note: this is just the default value; the actual switch will happen in code dynamically.

    Here is what the form looks like with some layout and formatting:

    Create the function to obtain the data source items:

    1. Choose Programming | Microsoft Script Editor from the Tools menu (or press Alt+Shift+F11).
    2. Add the following function to your code:

    function findDataCollection()
    {
        var selectedDataSource = XDocument.DOM.selectSingleNode("/ns1:Sample/SelectedDataSource");
        return XDocument.DOM.selectNodes("/ns1:Sample/Set"+selectedDataSource.text+"/Set"+selectedDataSource.text+"Item");
    }

    1. Save, and then close the Microsoft Script Editor.

    This function returns a set of items which we will use to fill the drop-down entries.

    Modify the XSL file:

    1. Choose Extract Form Files from the File menu.
    2. Close InfoPath.
    3. Using a text editor, open View1.xsl.
    4. Find:

    <xsl:if test="not(Set1/Set1Item[.=$val] or $val='')">
        <option selected="selected">
            <xsl:attribute name="value">
                <xsl:value-of select="$val"/>
            </xsl:attribute>
            <xsl:value-of select="$val"/>
        </option>
    </xsl:if>
    <xsl:for-each select="Set1/Set1Item">
        <option>
            <xsl:attribute name="value">
                <xsl:value-of select="."/>
            </xsl:attribute>
            <xsl:if test="$val=.">
                <xsl:attribute name="selected">selected</xsl:attribute>
            </xsl:if>
            <xsl:value-of select="."/>
        </option>
    </xsl:for-each>

    1. Replace with:

    <xsl:if test="$val=''"> <!-- just to make the code more uniform -->
        <option selected="selected">
            <xsl:attribute name="value">
                <xsl:value-of select="$val"/>
            </xsl:attribute>
            <xsl:value-of select="$val"/>
        </option>
    </xsl:if>
    <xsl:for-each select="xdExtension:findDataCollection()">
        <option>
            <xsl:attribute name="value">
                <xsl:value-of select="."/>
            </xsl:attribute>
            <xsl:if test="$val=.">
                <xsl:attribute name="selected">selected</xsl:attribute>
            </xsl:if>
            <xsl:value-of select="."/>
        </option>
    </xsl:for-each>

    At this point the drop-down uses the findDataCollection() function to determine the data source of its entries. This causes the list of items to be dependant on the value selected in SelectedDataSource. With this solution, if we select a value and then switch the data source, then the old value remains selected. If we want to clear TextField, we can easily use a rule or the onAfterChange event on the SelectedDataSource field.

    Conclusion:

    After these simple steps, the values that can be selected for TextField depends on the value of the SelectedDataSource field. The procedure is almost the same as if you wanted to dynamically bind a field to a control (e.g. Drop-Down List Box, Expression Box, Text Box, etc.). However, there is a side effect: after the change is done in the XSL, it is no longer possible to use the InfoPath designer to modify the dynamically bound-control. With this in mind, it is better to set everything you need (data validation, rules, conditional formatting, etc.) before you manually edit the XSL file.

Copyright © 2003-2019 Qdabra Software. All rights reserved.
View our Terms of Use.