In this Chapter:

  • Set Up the Initial Form
  • Create a Changed Event Method
  • Create a Namespace Variable
  • Access the Secondary Data Source
  • Loop Through the Secondary Data Source
  • Populate the Repeating Table
  • Clear Previous Entries
  • What Does the Final Solution Look Like?

This chapter covers the steps necessary to dynamically populate a repeating table. Displaying data from a data source in a repeating table is fairly straightforward using rules and filters. However, in this overall scenario, you need to populate a repeating group in your form with data from a data source. The data is dependent on another selection in your form.

Changing the selection in the form queries the data source based on that selection and populates a repeating table with the data. If the selection changes, the repeating table entries need to be cleared and repopulated with the new set of data.

To clarify the data sources, the external data source is a secondary data source, and the repeating table is bound as a repeating group of fields in the main data source.

Set Up the Initial Form

Scenario/Problem: You need to set up the initial form.

Solution: The initial form contains at least a selection field and a repeating group of fields to populate. The selection field can be populated by a data source if required. A secondary data source exists to populate the repeating table.

To set up the initial form, follow these steps:

Figure 17.1 Adding the controls to the form performs the initial form setup.
Figure 17.1 Adding the controls to the form performs the initial form setup.
Figure 17.2 Setting the query field value retrieves the related data.
Figure 17.2 Setting the query field value retrieves the related data.
Figure 17.3 Changing the selection field changes the data source repeating table.
Figure 17.3 Changing the selection field changes the data source repeating table.

So now the challenge is to place those entries of the dependent data source into the repeating table of the form.

Create a Changed Event Method

Scenario/Problem: You need to create a changed event method on a control.

Solution: Select the control and click the Changed Event button on the Developer ribbon bar.

Creating any methods produces code-behind in your form. For the overall scenario of this chapter, you need to generate a changed event method and place the code within that method.

For the example, select the drop-down list control and then click the Changed Event button on the Developer ribbon bar to generate the code-behind method, as shown in Figure 17.4.

Figure 17.4 Clicking Changed Event generates the code-behind method.
Figure 17.4 Clicking Changed Event generates the code-behind method.

To use code-behind, you need Microsoft Office Visual Studio Tools for Applications (VSTA) installed. If you do not have this installed, you may change the Microsoft InfoPath 2010 program in the Control Panel and select the VSTA option under Microsoft Office, Microsoft InfoPath, .NET Programmability Support.

The code is generated with an event handler declaration and a blank changed method, as shown in Figure 17.5.

Figure 17.5 Generating the code produces the event handler and changed method.
Figure 17.5 Generating the code produces the event handler and changed method.

Create a Namespace Variable

Scenario/Problem: You need to create a namespace variable.

Solution: Declare a string variable and set that to the namespace using the NamespaceManager object.

Coding with InfoPath involves using XML/XPath objects and methods as well as XPath expressions. A key element in using the XML/XPath methods is the namespace that is used for the XML data retrieval. The NamespaceManager object enables you to look up the namespace. By default, the namespace in InfoPath data is my.

Because the namespace is used throughout various methods in this solution, the first line of code in the changed method is a string variable declaration, as shown in **Listing 17.1. **


Access the Secondary Data Source

Scenario/Problem: You need to access the secondary data source.

Solution: Create DataSource and XPath objects using the secondary data source information.

The next step in the overall solution is to declare objects based on the secondary data source. You need the name of the secondary data source and the XPath of the rows that are returned. To retrieve the XPath of the rows returned, follow these steps:

Figure 17.6 Selecting Copy XPath places the XPath string into the Clipboard.
Figure 17.6 Selecting Copy XPath places the XPath string into the Clipboard.

The secondary data source setup code is shown in Listing 17.2. Paste the XPath from the previous steps into the XPathNavigator Select method. Place this block of code after the namespace variable.

Loop Through the Secondary Data Source

Scenario/Problem: You need to loop through the secondary data source.

Solution: Create a while loop to loop through the rows.

The loop is the main component of populating the repeating table. You loop through the secondary data source through the XPathNodeIterator collection (rows) that you defined in the previous section, retrieving the values from each row. The code to perform this is shown in Listing 17.3. Place this after the secondary data source setup. You will add more code to the loop in the next section.

Check the XPath of the secondary data source fields to determine how to call reference their nodes.

The variables defined in the loop should correspond to the fields that are returned from the secondary data source.

Populate the Repeating Table

Scenario/Problem: You need to populate the repeating table.

Solution: Use the XMLWriter to write the values from the secondary data source to the repeating group in the form.

The repeating table is actually part of the main data source, so you can access that and use the XMLWriter to write the field values from the secondary data source to the table.

You will need the names of the groups and the fields that are bound to the repeating table in the form. In this example, the groups are group1 and groupRepeat, and the fields are field1, field2, and field3.

Place the code in Listing 17.4 within the while loop from the preceding section.

Copy the XPath from the repeating group to ensure the correct path is entered.

The order in which you write the values to the table should be the order that they appear in the main data source. Otherwise, you will receive a non-datatype schema validation error.

Clear Previous Entries

Scenario/Problem: You need to clear previous entries.

Solution: Loop through the repeating table and clear the values.

If you preview the form at this point, you will notice that every time you select a value from the selection drop-down, the repeating table is populated with more and more entries (along with a blank row at the top). You therefore need to clear any previous entries before the repeating table is populated. Place the code listed in Listing 17.4 somewhere before the while loop.

What Does the Final Solution Look Like?

When all the code has been entered into the method properly, previewing the form populates the repeating table based on the selection in the drop-down, as shown in Figure 17.7.

Figure 17.7 Changing the selection populates the repeating table.
Figure 17.7 Changing the selection populates the repeating table.

Listing 17.5 shows the full code listing for the changed method.

LISTING 17.1 Namespace Declaration

  //Namespace variable
  string myNamespace = NamespaceManager.LookupNamespace(“my”);

LISTING 17.2 Secondary Data Source Setup

  //Secondary data source setup
  DataSource ds = DataSources[“OFFICES”];
  XPathNavigator domNav = ds.CreateNavigator();
  XPathNodeIterator rows = domNav.Select
(“/dfs:myFields/dfs:dataFields/d:SharePointListItem_RW”, 
NamespaceManager);

LISTING 17.3 Loop Through the Secondary Data Source

//Loop through the secondary data source
while (rows.MoveNext())
{
string office = rows.Current.SelectSingleNode(“D:TITLE”, 
NamespaceManager).Value.ToString();
      string region = rows.Current.SelectSingleNode(“D:REGION”, 
NamespaceManager).Value.ToString();
      string id = rows.Current.SelectSingleNode(“D:ID”,
 NamespaceManager).Value.ToString();
 }

LISTING 17.4 Populate the Repeating Table

//Populate the repeating table
using (XmlWriter writer = MainDataSource.CreateNavigator().SelectSingleNode(“/my:myFields/my:group1”, NamespaceManager).AppendChild()) 
{ 
     writer.WriteStartElement(“groupRepeat”, myNamespace);
     writer.WriteElementString(“field1”,myNamespace,office);
     writer.WriteElementString(“field2”, myNamespace,region); 
     writer.WriteElementString(“field3”, myNamespace,id); 
     writer.WriteEndElement(); 
     writer.Close(); 
}

LISTING 17.4 Clear Previous Entries

//Clear previous entries
XPathNavigator rTable = MainDataSource.CreateNavigator();
XPathNodeIterator tableRows = 
rTable.Select(“/my:myFields/my:group1/my:groupRepeat”, 
NamespaceManager);
if (tableRows.Count > 0)
{

LISTING 17.4 Clear Previous Entries (continued)

   for (int i = tableRows.Count; i > 0; i--)
  {
     XPathNavigator reTable = MainDataSource.CreateNavigator();
     XPathNavigator reTableRows = 
reTable.SelectSingleNode(“/my:myFields/my:group1/my:groupRepeat[“ + i
 + “]”, NamespaceManager);
     reTableRows.DeleteSelf();
   }
}

LISTING 17.5 Fully Changed Method

public void selection_Changed(object sender, XmlEventArgs e)
        {
            
            //Namespace variable
            string myNamespace = NamespaceManager.LookupNamespace(“my”);

            //Clear previous entries
            XPathNavigator rTable = MainDataSource.CreateNavigator();
     XPathNodeIterator tableRows = 
rTable.Select(“/my:myFields/my:group1/my:groupRepeat”, 
NamespaceManager);
            if (tableRows.Count > 0)
            {


                for (int i = tableRows.Count; i > 0; i--)
                {
                    XPathNavigator reTable =
                    MainDataSource.CreateNavigator();
                    XPathNavigator reTableRows =

                    reTable.SelectSingleNode
(“/my:myFields/my:group1/my:groupRepeat[“ + i + “]”, 
NamespaceManager);
                    reTableRows.DeleteSelf();
                }
            }

            //Secondary data source setup
            DataSource ds = DataSources[“Offices”];
            XPathNavigator domNav = ds.CreateNavigator();
            XPathNodeIterator rows = domNav.Select(“/dfs:myFields/dfs:dataFields/d:SharePointListItem_RW”, NamespaceManager);

        
            //Loop through the secondary data source
            while (rows.MoveNext())
            {
                string office = 
rows.Current.SelectSingleNode(“d:Title”, 
NamespaceManager).Value.ToString();
                string region = rows.Current.SelectSingleNode(“d:Region”, 
NamespaceManager).Value.ToString();
                string id = 

LISTING 17.5 Fully Changed Method (continued)

rows.Current.SelectSingleNode(“d:ID”, 
NamespaceManager).Value.ToString();

             //Populate the repeating table
             using (XmlWriter writer = 

MainDataource.CreateNavigator().SelectSingleNode(“/my:myFields/my:group1”, NamespaceManager).AppendChild())
        {
           writer.WriteStartElement(“groupRepeat”, myNamespace);
           writer.WriteElementString(“field1”, myNamespace, office);
           writer.WriteElementString(“field2”, myNamespace, region);
           writer.WriteElementString(“field3”, myNamespace, id);
           writer.WriteEndElement();
           writer.Close();
        }

            }
        
        }