July 2005 - Posts - Greg Collins Sign in | Join | Help in Greg Collins Tutorials (Entire Site) InfoPath Dev InfoPath Dev is dedicated to bringing you the information and tools you need to be successful in your Microsoft Office InfoPath development projects. Home Blogs Forums Photos Downloads This Blog Home About Syndication RSS Atom Comments RSS Recent Posts Swap the AD Alias and Name Fields in Place Create a Split Public/Private Form Display a Save As Dialog Box Highlight the Active Field Use the SharePoint '[Me]' Filter with a Promoted Property Tags Active Server ADWS Alias ASPX Background Borders Bugs Bullets and Numbering Buttons Cache Cascading Check Boxes Code concat() Conditional Formatting Conditional Visibility copy-of count Cross-Domain current Data Validation Debugging DisplayName domEventHandlers E-Mail Error Errors Events Expression Boxes Extract Form Files File Extension File Types Filters Focus Footer Formatting Forms Full Trust GetNamedNodeProperty Greg Collins Header Help Hyperlinks Internet Explorer Lists Managed Code Me Namespaces New NewFromSolution NewFromSolutionWithData number Numbered Lists OnAfterChange OnClick OnContextChange OnLoad OnSwitchView Operating System Option Buttons Outlook Picture Pictures position preceding preceding-sibling Preserve Code Blocks Printing processing-instructions Promoted Property References RegForm Repeating Sections Repeating Tables Rich Text Boxes Roles Rules Save As Schema Script Secondary Data Sources Sections Security SetNamedNodeProperty SharePoint SQL Style Sheets Submit Task Panes Template Text Boxes Tile Views Visual Studio Warning Windows Explorer Workarounds xdExtension xdXDocument XPath Archives October 2009 (1) April 2009 (1) March 2006 (1) November 2005 (1) September 2005 (1) July 2005 (4) June 2005 (24) March 2005 (2) January 2005 (1) November 2004 (1) October 2004 (1) September 2004 (6) August 2004 (5) July 2004 (20) June 2004 (5) Greg Collins July 2005 - Posts Create a Repeating Cascading List from a Hierarchical Data Source It is common to need two or more list boxes where the choices in one are dependant on the value of another. This is known as a cascading list. A cascade can occur with as few as two levels up to any number of levels. Some common scenarios which require cascading lists are:Location: State / CityVehicle: Year / Make / ModelSchool: Year / Semester / Class / InstructorAs the number of levels in the cascade increases, so does the complexity of the process and work involved. Also, if the cascading list is presented inside of a repeating table or repeating section you must account for another issue: data crossover. Data crossover means that the options presented in a cascade on a given row will be affected by earlier selected values from other rows—thus destroying the true cascading effect.In this task we will create a hierarchical secondary data source containing the values used to populate our lists. We will then create a three-level repeating cascading list using drop-down list boxes. We create three levels of cascade to reveal the compounding complexity involved for level three and beyond. We will resolve the issue regarding data crossover using the current function. And finally, we ensure valid selection combinations by clearing selected list values as selections earlier in the cascade are changed.THE HIERARCHICAL SECONDARY DATA SOURCEHierarchical data sources are commonly created for use in XML, and are typically more structured and organized than a flat data source. There are numerous ways to organize the hierarchy; we have arbitrarily chosen a structure that suits this task. The hierarchical structure normally ensures that only unique values appear each list. If, however, you find that filtering for unique values is still needed, refer to Display Only Unique Options in a List. Let's start by creating the hierarchical secondary data source.Create the hierarchical secondary data source:Copy the following code into a text editor, and then save the file as Vehicles - Hierarchical Data Source.xml. This file will be used as a secondary data source in our form. <?xml version="1.0" encoding="UTF-8"?><Vehicles> <Year value="1963"> <Make value="Chevrolet"> <Model value="Corvette"/> <Model value="Nova"/> </Make> <Make value="Porsche"> <Model value="356"/> <Model value="Carrera"/> </Make> </Year> <Year value="1973"> <Make value="Ford"> <Model value="Bronco"/> <Model value="Mustang"/> <Model value="Pinto"/> </Make> <Make value="Toyota"> <Model value="Celica"/> <Model value="Land Cruiser"/> </Make> </Year> <Year value="1979"> <Make value="Jaguar"> <Model value="XJ6"/> </Make> <Make value="Pontiac"> <Model value="Trans Am"/> </Make> <Make value="Volvo"> <Model value="240"/> <Model value="244DL"/> </Make> </Year> <Year value="1987"> <Make value="Dodge"> <Model value="Ram Charger"/> <Model value="Grand Caravan"/> </Make> <Make value="Honda"> <Model value="Civic"/> <Model value="Prelude"/> </Make> <Make value="Nissan"> <Model value="300ZX"/> <Model value="Pulsar"/> <Model value="Sentra"/> </Make> </Year> <Year value="1999"> <Make value="GMC"> <Model value="Jimmy"/> <Model value="Sierra 2500 HD"/> <Model value="Yukon"/> </Make> <Make value="Honda"> <Model value="Passport"/> <Model value="Prelude"/> <Model value="CR-V"/> </Make> <Make value="Jeep"> <Model value="Cherokee"/> </Make> <Make value="Mercury"> <Model value="Grand Marquis"/> <Model value="Sable"/> <Model value="Villager"/> </Make> <Make value="Pontiac"> <Model value="Firebird"/> <Model value="Montana"/> <Model value="Sunfire"/> </Make> </Year> <Year value="2003"> <Make value="Dodge"> <Model value="Dakota"/> <Model value="Caravan"/> <Model value="Ram Charger"/> <Model value="Viper"/> </Make> <Make value="Mercury"> <Model value="Sable"/> </Make> </Year> <Year value="2004"> <Make value="Dodge"> <Model value="Stratus"/> <Model value="Viper"/> </Make> <Make value="Ford"> <Model value="Crown Victoria"/> <Model value="F250"/> <Model value="Thunderbird"/> </Make> <Make value="GMC"> <Model value="Sierra 3500"/> </Make> <Make value="Jeep"> <Model value="Grand Cherokee"/> <Model value="Liberty"/> </Make> </Year></Vehicles>THE FORMNow that we have our hierarchical secondary data source we are ready to create our form. First we will design a simple schema to support a three-level repeating cascading list. Then we will design the layout using drop-down list boxes in a repeating table. When the layout is complete we will focus on creating the repeating cascade.Add the secondary data source to a form:Design a new blank form.Choose Data Connections from the Tools menu, and then click Add.In the Data Connection Wizard, select Receive Data, and then click Next.Select XML Document, and then click Next.Click Browse, locate and select the Vehicles - Hierarchical Data Source.xml file, click Open, and then click Next.Click Finish, click Yes, and then click Close.Create the schema:Open the Data Source task pane.Add a Group named Vehicles.Select the Vehicles group, and then add a Repeating Group named Vehicle.Select the Vehicle group, and then add three Text Fields named Year, Make, and Model.Design the view:Right-click Vehicle, and then choose Repeating Table.Select all three header row cells, and then set the font size to 8.Right-click each of the three text boxes, and then choose Change To | Drop-Down List Box. The results are shown in Figure 1.Figure 1. Layout of the repeating cascading drop-down list boxes.Double-click the repeating table label.On the Data tab of the Repeating Table Properties dialog box, change the insert button hint text to Insert Vehicle, and then click OK.THE CASCADING LISTSWith the form layout complete we will now turn our attention to the meat of the task: making one repeating list cascade off of another. The process is not very difficult, but can become increasingly complex as the number of cascade levels increases. Creating a cascade requires the use of filters. The options displayed in one list box are filtered based on values selected in earlier list boxes. Because our cascade is in a repeating structure, we must use the current function to ensure the filter does not crossover to values in other rows. Let's populate each drop-down list box using our secondary data source and create the cascade filters.Populate the Year drop-down list:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Hierarchical Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, select Vehicles/Year/value, and then click OK twice to close the open dialog boxes.Populate the Make drop-down list:Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Hierarchical Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, and then select Vehicles/Year/Make/value.Filter the Make drop-down list based on the selected Year in the current row:Click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select Select A Field Or Group from the first drop-down list.In the Select A Field Or Group dialog box, select Vehicles/Year/value, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Use A Formula.Type the following formula (as shown in Figure 2):current()/my:YearFigure 2. Filtering to compare the Year to the value on the current row.Click OK five times to close all open dialog boxes.We mentioned you would encounter the issue of data crossover. An example of data crossover is shown in the difference between Figure 3 and 4. Without using the current function the vehicle make will be filtered on all years currently selected in the repeating table, presenting the user with invalid choice combinations. Thus if you have 3 rows with the years 1963, 1979 and 2004 selected, each of the Make drop-down lists will contain a list of makes for all three of those selected years, as shown in Figure 4. By properly using the current function, we avoid data crossover by limiting the choices in the Make drop-down list to only those of the selected Year on the same row, as shown in Figure 3.Figure 3. Vehicle makes filtered by year using the current function.Figure 4. Vehicle makes filtered by year without using the current function.At this point you have created a two-level repeating cascade. The options in the Make drop-down list are filtered based on the selected Year in the current row. You can test this by previewing your form. Now let's create the level-three repeating cascade, which will reveal the compounding complexity involved in creating each additional level of cascade from here.Populate the Model drop-down list:Double-click the Model drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Hierarchical Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, and then select Vehicles/Year/Make/Model/value.Filter the Model drop-down list based on the selected Year in the current row:Click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select Select A Field Or Group from the first drop-down list.In the Select A Field Or Group dialog box, select Vehicles/Year/value, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Use A Formula.In the Insert A Formula dialog box, type the following formula:current()/my:YearClick OK.Filter the Model drop-down list based on the selected Make in the current row:Click And to create a second filter condition.In the first drop-down list of the second filter condition, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Vehicles/Year/Make/value, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Use A Formula.In the Insert A Formula dialog box, type the following formula:current()/my:MakeClick OK. The two filter conditions are shown in Figure 5.Figure 5. Filtering the third level of a repeating cascading list.Click OK four times to close all open dialog boxes.You have now created a three-level repeating cascade. Preview the form and test the functionality of the drop-down list boxes. You may discover an issue: you can create invalid selection combinations. We will resolve this issue in the next section.CLEARING SELECTIONS AFTER CHANGESOne issue with cascading lists that needs to be addressed is that when a selection is changed in an earlier level the selections following that change are likely to be invalid. For example, if you select year 1963 and model Chevrolet, and then select year 1973, Chevrolet remains the selected model, even though our data source does not list it as a model for 1973. The old value needs to be cleared so that invalid selection combinations cannot exist. This can be easily corrected with Rules.With some extra work, you can probably determine whether the following selected values are still valid and clear only invalid ones, but there are advantages to just clearing each following selected value. One advantage is that rules can cascade as well—like a Domino effect. As one value is changed, the next value is cleared; clearing that value triggers the next value to clear, and so on. Rules automatically affect the current row, so there is no need to filter using the current function in the rule.The rules we create will have no condition so that they will be processed every time the selected value changes. To clear the selected value of a field, we leave the Value text box of the rule blank.Clear the selected Make when the selected Year changes:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box, click Rules, and then click Add.Name the rule Clear Make, and then click Add Action.In the Action dialog box, select Set A Field's Value from the Action drop-down list.Click the Select XPath button to the right of the Field text box, and then select myFields/Vehicles/Vehicle/Make in the Main data source.Click OK five times to close all open dialog boxes.Clear the selected Model when the selected Make changes:Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box, click Rules, and then click Add.Name the rule Clear Model, and then click Add Action.In the Action dialog box, select Set A Field's Value from the Action drop-down list.Click the Select XPath button to the right of the Field text box, and then select myFields/Vehicles/Vehicle/Model in the Main data source.Click OK five times to close all open dialog boxes.Try it:You have now created a three-level repeating cascading list that prevents invalid selection combinations. Preview the form and try various selection combinations.©2005 Greg Collins. All rights reserved. Licensed to Autonomy Systems, LLC for display on InfoPathDev.com. Posted Jul 14 2005, 05:06 PM by Greg Collins with 3 comment(s) Filed under: Filters, Secondary Data Sources, Lists, Cascading Create a Repeating Cascading List from a Flat Data Source It is common to need two or more list boxes where the choices in one are dependant on the value of another. This is known as a cascading list. A cascade can occur with as few as two levels up to any number of levels. Some common scenarios which require cascading lists are:Location: State / CityVehicle: Make / Model / TrimSchool: Year / Semester / Class / InstructorAs the number of levels in the cascade increases, so does the complexity of the process and work involved. Also, if the cascading list is presented inside of a repeating table or repeating section you must account for another issue: data crossover. Data crossover means that the options presented in a cascade on a given row will be affected by earlier selected values from other rows—thus destroying the true cascading effect.In this task we will create a flat secondary data source containing the values used to populate our lists. We will then create a three-level repeating cascading list using drop-down list boxes. We create three levels of cascade to reveal the compounding complexity involved for level three and beyond. Because of the nature of the flat data source, we will filter each list to ensure that only unique values are displayed. We will resolve the issue regarding data crossover using the current function. And finally, we ensure valid selection combinations by clearing selected list values as selections earlier in the cascade are changed.THE FLAT SECONDARY DATA SOURCEFlat data sources are commonly returned from databases, Web services, and SharePoint. A flat data source has no hierarchy in the structure; it is simply a list of identical elements, each with an identical set of attributes. Only the values of the attributes change. Flat data sources also require additional filtering to ensure that only unique values appear in the drop-down lists. Let's start by creating the flat secondary data source.Create the flat secondary data source:Copy the following code into a text editor, and then save the file as Vehicles - Flat Data Source.xml. This file will be used as a secondary data source in our form.<?xml version="1.0" encoding="UTF-8"?><Vehicles> <Vehicle year="1963" make="Chevrolet" model="Corvette"/> <Vehicle year="1963" make="Chevrolet" model="Nova"/> <Vehicle year="1963" make="Porsche" model="356"/> <Vehicle year="1963" make="Porsche" model="Carrera"/> <Vehicle year="1973" make="Ford" model="Bronco"/> <Vehicle year="1973" make="Ford" model="Mustang"/> <Vehicle year="1973" make="Ford" model="Pinto"/> <Vehicle year="1973" make="Toyota" model="Celica"/> <Vehicle year="1973" make="Toyota" model="Land Cruiser"/> <Vehicle year="1979" make="Jaguar" model="XJ6"/> <Vehicle year="1979" make="Pontiac" model="Trans Am"/> <Vehicle year="1979" make="Volvo" model="240"/> <Vehicle year="1979" make="Volvo" model="244DL"/> <Vehicle year="1987" make="Dodge" model="Ram Charger"/> <Vehicle year="1987" make="Dodge" model="Grand Caravan"/> <Vehicle year="1987" make="Honda" model="Civic"/> <Vehicle year="1987" make="Honda" model="Prelude"/> <Vehicle year="1987" make="Nissan" model="300ZX"/> <Vehicle year="1987" make="Nissan" model="Pulsar"/> <Vehicle year="1987" make="Nissan" model="Sentra"/> <Vehicle year="1999" make="GMC" model="Jimmy"/> <Vehicle year="1999" make="GMC" model="Sierra 2500 HD"/> <Vehicle year="1999" make="GMC" model="Yukon"/> <Vehicle year="1999" make="Honda" model="Passport"/> <Vehicle year="1999" make="Honda" model="Prelude"/> <Vehicle year="1999" make="Honda" model="CR-V"/> <Vehicle year="1999" make="Jeep" model="Cherokee"/> <Vehicle year="1999" make="Mercury" model="Grand Marquis"/> <Vehicle year="1999" make="Mercury" model="Sable"/> <Vehicle year="1999" make="Mercury" model="Villager"/> <Vehicle year="1999" make="Pontiac" model="Firebird"/> <Vehicle year="1999" make="Pontiac" model="Montana"/> <Vehicle year="1999" make="Pontiac" model="Sunfire"/> <Vehicle year="2003" make="Dodge" model="Dakota"/> <Vehicle year="2003" make="Dodge" model="Caravan"/> <Vehicle year="2003" make="Dodge" model="Ram Charger"/> <Vehicle year="2003" make="Dodge" model="Viper"/> <Vehicle year="2003" make="Mercury" model="Sable"/> <Vehicle year="2004" make="Dodge" model="Stratus"/> <Vehicle year="2004" make="Dodge" model="Viper"/> <Vehicle year="2004" make="Ford" model="Crown Victoria"/> <Vehicle year="2004" make="Ford" model="F250"/> <Vehicle year="2004" make="Ford" model="Thunderbird"/> <Vehicle year="2004" make="GMC" model="Sierra 3500"/> <Vehicle year="2004" make="Jeep" model="Grand Cherokee"/> <Vehicle year="2004" make="Jeep" model="Liberty"/></Vehicles>THE FORMNow that we have our flat secondary data source we are ready to create our form. First we will design a simple schema to support a three-level repeating cascading list. Then we will design the layout using drop-down list boxes in a repeating table. When the layout is complete we will focus on creating the repeating cascade.Add the secondary data source to a form:Design a new blank form.Choose Data Connections from the Tools menu, and then click Add.In the Data Connection Wizard, select Receive Data, and then click Next.Select XML Document, and then click Next.Click Browse, locate and select the Vehicles - Flat Data Source.xml file, click Open, and then click Next.Click Finish, click Yes, and then click Close.Create the schema:Open the Data Source task pane.Add a Group named Vehicles.Select the Vehicles group, and then add a Repeating Group named Vehicle.Select the Vehicle group, and then add three Text Fields named Year, Make, and Model.Design the view:Right-click Vehicle, and then choose Repeating Table.Select all three header row cells, and then set the font size to 8.Right-click each of the three text boxes, and then choose Change To | Drop-Down List Box. The results are shown in Figure 1.Figure 1. Layout of the repeating cascading drop-down list boxes.Double-click the repeating table label.On the Data tab of the Repeating Table Properties dialog box, change the insert button hint text to Insert Vehicle, and then click OK.THE CASCADING LISTSWith the form layout complete we will now turn our attention to the meat of the task: making one list cascade off of another. The process is not very difficult, but can become increasingly complex as the number of cascade levels increases. Creating a cascade requires the use of filters. The options displayed in one list box are filtered based on values selected in earlier list boxes. Because our cascade is in a repeating structure, we must use the current function to ensure the filter does not crossover to values in other rows. Let's populate each drop-down list box using our secondary data source and create the cascade filters.Populate the Year drop-down list:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Flat Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, select Vehicles/Vehicle/year, and then click OK twice to close the open dialog boxes.Populate the Make drop-down list:Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Flat Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, and then select Vehicles/Vehicle/make.Filter the Make drop-down list based on the selected Year in the current row:Click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select Select A Field Or Group from the first drop-down list.In the Select A Field Or Group dialog box, select Vehicles/Vehicle/year, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Use A Formula.Type the following formula (as shown in Figure 2):current()/my:YearFigure 2. Filtering to compare the Year to the value on the current row.Click OK five times to close all open dialog boxes.We mentioned you would encounter the issue of data crossover. An example of data crossover is shown in the difference between Figure 3 and 4 (please note that Figures 3 and 4 already account for unique value filtering). Without using the current function the vehicle make will be filtered on all years currently selected in the repeating table, presenting the user with invalid choice combinations. Thus if you have 3 rows with the years 1963, 1979 and 2004 selected, each of the Make drop-down lists will contain a list of makes for all three of those selected years, as shown in Figure 4. By properly using the current function, we avoid data crossover by limiting the choices in the Make drop-down list to only those of the selected Year on the same row, as shown in Figure 3.Figure 3. Vehicle makes filtered by year using the current function.Figure 4. Vehicle makes filtered by year without using the current function.At this point you have created a two-level repeating cascade. The options in the Make drop-down list are filtered based on the selected Year in the current row. You can test this by previewing your form. You will notice that each drop-down list contains repeated values. This is a byproduct of using a flat data source and will be corrected in the next section when we filter for unique values. Now let's create the level-three cascade, which will reveal the compounding complexity involved in creating each additional level of cascade from here.Populate the Model drop-down list:Double-click the Model drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Flat Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, and then select Vehicles/Vehicle/model.Filter the Model drop-down list based on the selected Year in the current row:Click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select Select A Field Or Group from the first drop-down list.In the Select A Field Or Group dialog box, select Vehicles/Vehicle/year, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Use A Formula.In the Insert A Formula dialog box, type the following formula:current()/my:YearClick OK.Filter the Model drop-down list based on the selected Make in the current row:Click And to create a second filter condition.In the first drop-down list of the second filter condition, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Vehicles/Vehicle/make, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Use A Formula.In the Insert A Formula dialog box, type the following formula:current()/my:MakeClick OK. The two filter conditions are shown in Figure 5.Figure 5. Filtering the third level of a repeating cascading list.Click OK four times to close all open dialog boxes.You have now created a three-level repeating cascade. Preview the form and test the functionality of the drop-down list boxes. You may discover two issues: first, the list options are not unique, and second, you can create invalid selection combinations. We will resolve these two issues in the next two sections.FILTERING LISTS FOR UNIQUE VALUESValues in flat data sources are usually repeated. Although this is important given the XML structure, it can lead to option bloat in your list box. It can only serve to confuse and frustrate the user to present them with numerous identical options. The answer is to filter the list to display only unique values. This can be done using XPath.It should be mentioned that just as the complexity of the cascade filters compounded with each additional cascade level, so do the complexity of the uniqueness filters. You will see this in the expression used to filter the Model drop-down list for unique values.Add a uniqueness filter to the Year drop-down list:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box, click the Select XPath button to the right of the Entries text box.In the Select A Field Or Group dialog box, click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select The Expression from the first drop-down list, and then type the following expression (as shown in Figure 6):not(. = ../preceding-sibling::Vehicle/@year)Figure 6. Filtering list options to display only unique values.Click OK four times to close all open dialog boxes.Add a uniqueness filter to the Make drop-down list:At each cascade level beyond the initial list box, your uniqueness filter must take into consideration the selection from each of the previous levels. Due to the nature of this filter, if you do not take the previous selections into consideration, you may inadvertently completely filter out all valid options.For example, in our sample secondary data source, vehicle years 1987 and 1999 both include the Honda make. If we did not account for the selected year, the Honda make would not appear as an option when year 1999 was selected. This is because the filter would identify that the Honda make appeared earlier in the secondary data source. The Dodge make in years 2003 and 2004 would also be completely filtered out because Dodge appears earlier, in year 1987. There are a few other makes and models in the sample secondary data source that would encounter this issue.Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box, click the Select XPath button to the right of the Entries text box.In the Select A Field Or Group dialog box, click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select The Expression from the first drop-down list, and then type the following expression:not(. = ../preceding-sibling::Vehicle[@year = current()/my:Year]/@make)Note that compared with the uniqueness filter we placed on the Year drop-down list box, there is an additional subfilter specified on the Vehicle node. The subfilter [@year = current()/my:Year] constrains the main filter to verify that we display unique values for each make within the selected year.Click OK four times to close all open dialog boxes.Add a uniqueness filter to the Model drop-down list:Double-click the Model drop-down list box.In the Drop-Down List Box Properties dialog box, click the Select XPath button to the right of the Entries text box.In the Select A Field Or Group dialog box, click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select The Expression from the first drop-down list, and then type the following expression:not(. = ../preceding-sibling::Vehicle[@year = current()/my:Year and @make = current()/my:Make]/@model)Just as we did with the uniqueness filter for the Make drop-down list above, here we have added an additional subfilter to guarantee that we are only eliminating repeated options from the list of models within the selected year and selected make.Click OK four times to close all open dialog boxes.If you can guarantee that the values, at any level of cascade, will always and forever be unique then you do not need to add the uniqueness filter. If, however, there is any doubt, it is always safer to add it. For more information on filtering lists for unique values, refer to Display Only Unique Options in a List.CLEARING SELECTIONS AFTER CHANGESOne issue with cascading lists that needs to be addressed is that when a selection is changed in an earlier level the selections following that change are likely to be invalid. For example, if you select year 1963 and model Chevrolet, and then select year 1973, Chevrolet remains the selected model, even though our data source does not list it as a model for 1973. The old value needs to be cleared so that invalid selection combinations cannot exist. This can be easily corrected with Rules.With some extra work, you can probably determine whether the following selected values are still valid and clear only invalid ones, but there are advantages to just clearing each following selected value. One advantage is that rules can cascade as well—like a Domino effect. As one value is changed, the next value is cleared; clearing that value triggers the next value to clear, and so on. Rules automatically affect the current row, so there is no need to filter using the current function in the rule.The rules we create will have no condition so that they will be processed every time the selected value changes. To clear the selected value of a field, we leave the Value text box of the rule blank.Clear the selected Make when the selected Year changes:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box, click Rules, and then click Add.Name the rule Clear Make, and then click Add Action.In the Action dialog box, select Set A Field's Value from the Action drop-down list.Click the Select XPath button to the right of the Field text box, and then select myFields/Vehicles/Vehicle/Make in the Main data source.Click OK five times to close all open dialog boxes.Clear the selected Model when the selected Make changes:Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box, click Rules, and then click Add.Name the rule Clear Model, and then click Add Action.In the Action dialog box, select Set A Field's Value from the Action drop-down list.Click the Select XPath button to the right of the Field text box, and then select myFields/Vehicles/Vehicle/Model in the Main data source.Click OK five times to close all open dialog boxes.Try it:You have now created a three-level repeating cascading list that filters for unique values and prevents invalid selection combinations. Preview the form and try various selection combinations.©2005 Greg Collins. All rights reserved. Licensed to Autonomy Systems, LLC for display on InfoPathDev.com. Posted Jul 14 2005, 04:03 PM by Greg Collins with 9 comment(s) Filed under: Filters, Secondary Data Sources, Lists, Cascading Create a Cascading List from a Hierarchical Data Source It is common to need two or more list boxes where the choices in one are dependant on the value of another. This is known as a cascading list. A cascade can occur with as few as two levels up to any number of levels. Some common scenarios which require cascading lists are:Location: State / CityVehicle: Year / Make / ModelSchool: Year / Semester / Class / InstructorAs the number of levels in the cascade increases, so does the complexity of the process and work involved. Also, if the cascading list is presented inside of a repeating table or repeating section you must account for another issue: data crossover. Repeating cascading lists are covered in Create a Repeating Cascading List from a Flat Data Source and Create a Repeating Cascading List from a Hierarchical Data Source.In this task we will create a hierarchical secondary data source containing the values used to populate our lists. We will then create a three-level non-repeating cascading list using drop-down list boxes. We create three levels of cascade to reveal the compounding complexity involved for level three and beyond. And finally, we ensure valid selection combinations by clearing selected list values as selections earlier in the cascade are changed.THE HIERARCHICAL SECONDARY DATA SOURCEHierarchical data sources are commonly created for use in XML, and are typically more structured and organized than a flat data source. There are numerous ways to organize the hierarchy; we have arbitrarily chosen a structure that suits this task. The hierarchical structure normally ensures that only unique values appear each list. If, however, you find that filtering for unique values is still needed, refer to Display Only Unique Options in a List. Let's start by creating the hierarchical secondary data source.Create the hierarchical secondary data source:Copy the following code into a text editor, and then save the file as Vehicles - Hierarchical Data Source.xml. This file will be used as a secondary data source in our form. <?xml version="1.0" encoding="UTF-8"?><Vehicles> <Year value="1963"> <Make value="Chevrolet"> <Model value="Corvette"/> <Model value="Nova"/> </Make> <Make value="Porsche"> <Model value="356"/> <Model value="Carrera"/> </Make> </Year> <Year value="1973"> <Make value="Ford"> <Model value="Bronco"/> <Model value="Mustang"/> <Model value="Pinto"/> </Make> <Make value="Toyota"> <Model value="Celica"/> <Model value="Land Cruiser"/> </Make> </Year> <Year value="1979"> <Make value="Jaguar"> <Model value="XJ6"/> </Make> <Make value="Pontiac"> <Model value="Trans Am"/> </Make> <Make value="Volvo"> <Model value="240"/> <Model value="244DL"/> </Make> </Year> <Year value="1987"> <Make value="Dodge"> <Model value="Ram Charger"/> <Model value="Grand Caravan"/> </Make> <Make value="Honda"> <Model value="Civic"/> <Model value="Prelude"/> </Make> <Make value="Nissan"> <Model value="300ZX"/> <Model value="Pulsar"/> <Model value="Sentra"/> </Make> </Year> <Year value="1999"> <Make value="GMC"> <Model value="Jimmy"/> <Model value="Sierra 2500 HD"/> <Model value="Yukon"/> </Make> <Make value="Honda"> <Model value="Passport"/> <Model value="Prelude"/> <Model value="CR-V"/> </Make> <Make value="Jeep"> <Model value="Cherokee"/> </Make> <Make value="Mercury"> <Model value="Grand Marquis"/> <Model value="Sable"/> <Model value="Villager"/> </Make> <Make value="Pontiac"> <Model value="Firebird"/> <Model value="Montana"/> <Model value="Sunfire"/> </Make> </Year> <Year value="2003"> <Make value="Dodge"> <Model value="Dakota"/> <Model value="Caravan"/> <Model value="Ram Charger"/> <Model value="Viper"/> </Make> <Make value="Mercury"> <Model value="Sable"/> </Make> </Year> <Year value="2004"> <Make value="Dodge"> <Model value="Stratus"/> <Model value="Viper"/> </Make> <Make value="Ford"> <Model value="Crown Victoria"/> <Model value="F250"/> <Model value="Thunderbird"/> </Make> <Make value="GMC"> <Model value="Sierra 3500"/> </Make> <Make value="Jeep"> <Model value="Grand Cherokee"/> <Model value="Liberty"/> </Make> </Year></Vehicles>THE FORMNow that we have our hierarchical secondary data source we are ready to create our form. First we will design a simple schema to support a three-level cascading list. Then we will design the layout using drop-down list boxes. When the layout is complete we will focus on creating the cascade.Add the secondary data source to a form:Design a new blank form.Choose Data Connections from the Tools menu, and then click Add.In the Data Connection Wizard, select Receive Data, and then click Next.Select XML Document, and then click Next.Click Browse, locate and select the Vehicles - Hierarchical Data Source.xml file, click Open, and then click Next.Click Finish, click Yes, and then click Close.Create the schema:Open the Data Source task pane.Add a Group named Vehicle.Select the Vehicle group, and then add three Text Fields named Year, Make, and Model.Design the view:Insert a 1x3 layout table into the view.From left to right, insert the Year, Make, and Model fields as Drop-Down List Boxes into the cells of the layout table, as shown in Figure 1.Figure 1. Layout of the cascading drop-down list boxes.THE CASCADING LISTSWith the form layout complete we will now turn our attention to the meat of the task: making one list cascade off of another. The process is not very difficult, but can become increasingly complex as the number of cascade levels increases. Creating a cascade requires the use of filters. The options displayed in one list box are filtered based on values selected in earlier list boxes. Let's populate each drop-down list box using our secondary data source and create the cascade filters.Populate the Year drop-down list:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Hierarchical Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, and then select Vehicles/Year/value, and then click OK twice to close the open dialog boxes.Populate the Make drop-down list:Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Hierarchical Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, and then select Vehicles/Year/Make/value.Filter the Make drop-down list based on the selected Year:Click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select Select A Field Or Group from the first drop-down list.In the Select A Field Or Group dialog box, select Vehicles/Year/value, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Main from the Data Source drop-down list, select myFields/Vehicle/Year, and then click OK (refer to Figure 2).Figure 2. Filtering the second level of a cascading list.Click OK four times to close all open dialog boxes.At this point you have created a two-level cascade. The options in the Make drop-down list are filtered based on the selected Year. You can test this by previewing your form. Now let's create the level-three cascade, which will reveal the compounding complexity involved in creating each additional level of cascade from here.Populate the Model drop-down list:Double-click the Model drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Hierarchical Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, and then select Vehicles/Year/Make/Model/value.Filter the Model drop-down list based on the selected Year:Click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select Select A Field Or Group from the first drop-down list.In the Select A Field Or Group dialog box, select Vehicles/Year/value, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Main from the Data Source drop-down list, select myFields/Vehicle/Year, and then click OK.Filter the Model drop-down list based on the selected Make:Click And to create a second filter condition.In the first drop-down list of the second filter condition, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Vehicles/Year/Make/value, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Main from the Data Source drop-down list, select myFields/Vehicle/Make, and then click OK (refer to Figure 3).Figure 3. Filtering the third level of a cascading list.Click OK four times to close all open dialog boxes.You have now created a three-level cascade. Preview the form and test the functionality of the drop-down list boxes. You may discover an issue: you can create invalid selection combinations. We will resolve this issue in the next section.CLEARING SELECTIONS AFTER CHANGESOne issue with cascading lists that needs to be addressed is that when a selection is changed in an earlier level the selections following that change are likely to be invalid. For example, if you select year 1963 and model Chevrolet, and then select year 1973, Chevrolet remains the selected model, even though our data source does not list it as a model for 1973. The old value needs to be cleared so that invalid selection combinations cannot exist. This can be easily corrected with Rules.With some extra work, you can probably determine whether the following selected values are still valid and clear only invalid ones, but there are advantages to just clearing each following selected value. One advantage is that rules can cascade as well—like a Domino effect. As one value is changed, the next value is cleared; clearing that value triggers the next value to clear, and so on.The rules we create will have no condition so that they will be processed every time the selected value changes. To clear the selected value of a field, we leave the Value text box of the rule blank.Clear the selected Make when the selected Year changes:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box, click Rules, and then click Add.Name the rule Clear Make, and then click Add Action.In the Action dialog box, select Set A Field's Value from the Action drop-down list.Click the Select XPath button to the right of the Field text box, and then select myFields/Vehicle/Make in the Main data source.Click OK five times to close all open dialog boxes.Clear the selected Model when the selected Make changes:Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box, click Rules, and then click Add.Name the rule Clear Model, and then click Add Action.In the Action dialog box, select Set A Field's Value from the Action drop-down list.Click the Select XPath button to the right of the Field text box, and then select myFields/Vehicle/Model in the Main data source.Click OK five times to close all open dialog boxes.Try it:You have now created a three-level cascading list that prevents invalid selection combinations. Preview the form and try various selection combinations.©2005 Greg Collins. All rights reserved. Licensed to Autonomy Systems, LLC for display on InfoPathDev.com. Posted Jul 06 2005, 10:06 AM by Greg Collins with 3 comment(s) Filed under: Filters, Secondary Data Sources, Lists, Cascading Create a Cascading List from a Flat Data Source It is common to need two or more list boxes where the choices in one are dependant on the value of another. This is known as a cascading list. A cascade can occur with as few as two levels up to any number of levels. Some common scenarios which require cascading lists are:Location: State / CityVehicle: Make / Model / TrimSchool: Year / Semester / Class / InstructorAs the number of levels in the cascade increases, so does the complexity of the process and work involved. Also, if the cascading list is presented inside of a repeating table or repeating section you must account for another issue: data crossover. Repeating cascading lists are covered in Create a Repeating Cascading List from a Flat Data Source and Create a Repeating Cascading List from a Hierarchical Data Source.In this task we will create a flat secondary data source containing the values used to populate our lists. We will then create a three-level non-repeating cascading list using drop-down list boxes. We create three levels of cascade to reveal the compounding complexity involved for level three and beyond. Because of the nature of the flat data source, we will filter each list to ensure that only unique values are displayed. And finally, we ensure valid selection combinations by clearing selected list values as selections earlier in the cascade are changed.THE FLAT SECONDARY DATA SOURCEFlat data sources are commonly returned from databases, Web services, and SharePoint. A flat data source has no hierarchy in the structure; it is simply a list of identical elements, each with an identical set of attributes. Only the values of the attributes change. Flat data sources also require additional filtering to ensure that only unique values appear in the drop-down lists. Let's start by creating the flat secondary data source.Create the flat secondary data source:Copy the following code into a text editor, and then save the file as Vehicles - Flat Data Source.xml. This file will be used as a secondary data source in our form.<?xml version="1.0" encoding="UTF-8"?><Vehicles> <Vehicle year="1963" make="Chevrolet" model="Corvette"/> <Vehicle year="1963" make="Chevrolet" model="Nova"/> <Vehicle year="1963" make="Porsche" model="356"/> <Vehicle year="1963" make="Porsche" model="Carrera"/> <Vehicle year="1973" make="Ford" model="Bronco"/> <Vehicle year="1973" make="Ford" model="Mustang"/> <Vehicle year="1973" make="Ford" model="Pinto"/> <Vehicle year="1973" make="Toyota" model="Celica"/> <Vehicle year="1973" make="Toyota" model="Land Cruiser"/> <Vehicle year="1979" make="Jaguar" model="XJ6"/> <Vehicle year="1979" make="Pontiac" model="Trans Am"/> <Vehicle year="1979" make="Volvo" model="240"/> <Vehicle year="1979" make="Volvo" model="244DL"/> <Vehicle year="1987" make="Dodge" model="Ram Charger"/> <Vehicle year="1987" make="Dodge" model="Grand Caravan"/> <Vehicle year="1987" make="Honda" model="Civic"/> <Vehicle year="1987" make="Honda" model="Prelude"/> <Vehicle year="1987" make="Nissan" model="300ZX"/> <Vehicle year="1987" make="Nissan" model="Pulsar"/> <Vehicle year="1987" make="Nissan" model="Sentra"/> <Vehicle year="1999" make="GMC" model="Jimmy"/> <Vehicle year="1999" make="GMC" model="Sierra 2500 HD"/> <Vehicle year="1999" make="GMC" model="Yukon"/> <Vehicle year="1999" make="Honda" model="Passport"/> <Vehicle year="1999" make="Honda" model="Prelude"/> <Vehicle year="1999" make="Honda" model="CR-V"/> <Vehicle year="1999" make="Jeep" model="Cherokee"/> <Vehicle year="1999" make="Mercury" model="Grand Marquis"/> <Vehicle year="1999" make="Mercury" model="Sable"/> <Vehicle year="1999" make="Mercury" model="Villager"/> <Vehicle year="1999" make="Pontiac" model="Firebird"/> <Vehicle year="1999" make="Pontiac" model="Montana"/> <Vehicle year="1999" make="Pontiac" model="Sunfire"/> <Vehicle year="2003" make="Dodge" model="Dakota"/> <Vehicle year="2003" make="Dodge" model="Caravan"/> <Vehicle year="2003" make="Dodge" model="Ram Charger"/> <Vehicle year="2003" make="Dodge" model="Viper"/> <Vehicle year="2003" make="Mercury" model="Sable"/> <Vehicle year="2004" make="Dodge" model="Stratus"/> <Vehicle year="2004" make="Dodge" model="Viper"/> <Vehicle year="2004" make="Ford" model="Crown Victoria"/> <Vehicle year="2004" make="Ford" model="F250"/> <Vehicle year="2004" make="Ford" model="Thunderbird"/> <Vehicle year="2004" make="GMC" model="Sierra 3500"/> <Vehicle year="2004" make="Jeep" model="Grand Cherokee"/> <Vehicle year="2004" make="Jeep" model="Liberty"/></Vehicles>THE FORMNow that we have our flat secondary data source we are ready to create our form. First we will design a simple schema to support a three-level cascading list. Then we will design the layout using drop-down list boxes. When the layout is complete we will focus on creating the cascade.Add the secondary data source to a form:Design a new blank form.Choose Data Connections from the Tools menu, and then click Add.In the Data Connection Wizard, select Receive Data, and then click Next.Select XML Document, and then click Next.Click Browse, locate and select the Vehicles - Flat Data Source.xml file, click Open, and then click Next.Click Finish, click Yes, and then click Close.Create the schema:Open the Data Source task pane.Add a Group named Vehicle.Select the Vehicle group, and then add three Text Fields named Year, Make, and Model.Design the view:Insert a 1x3 layout table into the view.From left to right, insert the Year, Make, and Model fields as Drop-Down List Boxes into the cells of the layout table, as shown in Figure 1.Figure 1. Layout of the cascading drop-down list boxes.THE CASCADING LISTSWith the form layout complete we will now turn our attention to the meat of the task: making one list cascade off of another. The process is not very difficult, but can become increasingly complex as the number of cascade levels increases. Creating a cascade requires the use of filters. The options displayed in one list box are filtered based on the values selected in earlier list boxes. Let's populate each drop-down list box using our secondary data source and create the cascade filters.Populate the Year drop-down list:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Flat Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, select Vehicles/Vehicle/year, and then click OK twice to close the open dialog boxes.Populate the Make drop-down list:Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Flat Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, select Vehicles/Vehicle/make.Filter the Make drop-down list based on the selected Year:Click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select Select A Field Or Group from the first drop-down list.In the Select A Field Or Group dialog box, select Vehicles/Vehicle/year, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Main from the Data Source drop-down list, select myFields/Vehicle/Year, and then click OK (refer to Figure 2).Figure 2. Filtering the second level of a cascading list.Click OK four times to close all open dialog boxes.At this point you have created a two-level cascade. The options in the Make drop-down list are filtered based on the selected Year. You can test this by previewing your form. Now let's create the level-three cascade, which will reveal the compounding complexity involved in creating each additional level of cascade from here.Populate the Model drop-down list:Double-click the Model drop-down list box.In the Drop-Down List Box Properties dialog box select Look Up Values In A Data Connection.Select Vehicles - Flat Data Source from the Data Connection drop-down list.Click the Select XPath button to the right of the Entries text box, and then select Vehicles/Vehicle/model.Filter the Model drop-down list based on the selected Year:Click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select Select A Field Or Group from the first drop-down list.In the Select A Field Or Group dialog box, select Vehicles/Vehicle/year, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Main from the Data Source drop-down list, select myFields/Vehicle/Year, and then click OK.Filter the Model drop-down list based on the selected Make:Click And to create a second filter condition.In the first drop-down list of the second filter condition, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Vehicles/Vehicle/make, and then click OK.In the second drop-down list, select Is Equal To.In the third drop-down list box, select Select A Field Or Group.In the Select A Field Or Group dialog box, select Main from the Data Source drop-down list, select myFields/Vehicle/Make, and then click OK (refer to Figure 3).Figure 3. Filtering the third level of a cascading list.Click OK four times to close all open dialog boxes.You have now created a three-level cascade. Preview the form and test the functionality of the drop-down list boxes. You may discover two issues: first, the list options are not unique, and second, you can create invalid selection combinations. These two issues will be resolved in the next two sections.FILTERING LISTS FOR UNIQUE VALUESValues in flat data sources are usually repeated. Although this is important given the XML structure, it can lead to option bloat in your list box. It can only serve to confuse and frustrate the user to present them with numerous identical options. The answer is to filter the list to display only unique values. This can be done using XPath.It should be mentioned that just as the complexity of the cascading filters compounded with each additional cascading level, so does the complexity of the uniqueness filters. You will see this in the expression used to filter the Model drop-down list for unique values.Add a uniqueness filter to the Year drop-down list:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box, click the Select XPath button to the right of the Entries text box.In the Select A Field Or Group dialog box, click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select The Expression from the first drop-down list, and then type the following expression (as shown in Figure 4):not(. = ../preceding-sibling::Vehicle/@year)Figure 4. Filtering list options to display only unique values.Click OK four times to close all open dialog boxes.Add a uniqueness filter to the Make drop-down list:At each cascade level beyond the initial list box, your uniqueness filter must take into consideration the selection from each of the previous levels. Due to the nature of this filter, if you do not take the previous selections into consideration, you may inadvertently completely filter out all valid options.For example, in our sample secondary data source, vehicle years 1987 and 1999 both include the Honda make. If we did not account for the selected year, the Honda make would not appear as an option when year 1999 was selected. This is because the filter would identify that the Honda make appeared earlier in the secondary data source. The Dodge make in years 2003 and 2004 would also be completely filtered out because Dodge appears earlier in year 1987. There are a few other makes and models in the sample secondary data source that would encounter this issue.Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box, click the Select XPath button to the right of the Entries text box.In the Select A Field Or Group dialog box, click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select The Expression from the first drop-down list, and then type the following expression:not(. = ../preceding-sibling::Vehicle[@year = current()/my:Vehicle/my:Year]/@make)Note that compared with the uniqueness filter we placed on the Year drop-down list box, there is an additional subfilter specified on the Vehicle node. The subfilter [@year = current()/my:Vehicle/my:Year] constrains the main filter to verify that we display unique values for each make within the selected year.Click OK four times to close all open dialog boxes.Add a uniqueness filter to the Model drop-down list:Double-click the Model drop-down list box.In the Drop-Down List Box Properties dialog box, click the Select XPath button to the right of the Entries text box.In the Select A Field Or Group dialog box, click Filter Data, and then click Add.In the Specify Filter Conditions dialog box, select The Expression from the first drop-down list, and then type the following expression:not(. = ../preceding-sibling::Vehicle[@year = current()/my:Vehicle/my:Year and @make = current()/my:Vehicle/my:Make]/@model)Just as we did with the uniqueness filter for the Make drop-down list above, here we have added an additional subfilter to guarantee that we are only eliminating repeated options from the list of models within the selected year and selected make.Click OK four times to close all open dialog boxes.If you can guarantee that the values, at any level of cascade, will always and forever be unique then you do not need to add the uniqueness filter. If, however, there is any doubt, it is always safer to add it. For more information on filtering lists for unique values, refer to Display Only Unique Options in a List.CLEARING SELECTIONS AFTER CHANGESOne issue with cascading lists that needs to be addressed is that when a selection is changed in an earlier level the selections following that change are likely to be invalid. For example, if you select year 1963 and model Chevrolet, and then select year 1973, Chevrolet remains the selected model, even though our data source does not list it as a model for 1973. The old value needs to be cleared so that invalid selection combinations cannot exist. This can be easily corrected with Rules.With some extra work, you can probably determine whether the following selected values are still valid and clear only invalid ones, but there are advantages to just clearing each following selected value. One advantage is that rules can cascade as well—like a Domino effect. As one value is changed, the next value is cleared; clearing that value triggers the next value to clear, and so on.The rules we create will have no condition so that they will be processed every time the selected value changes. To clear the selected value of a field, we leave the Value text box of the rule blank.Clear the selected Make when the selected Year changes:Double-click the Year drop-down list box.In the Drop-Down List Box Properties dialog box, click Rules, and then click Add.Name the rule Clear Make, and then click Add Action.In the Action dialog box, select Set A Field's Value from the Action drop-down list.Click the Select XPath button to the right of the Field text box, and then select myFields/Vehicle/Make in the Main data source.Click OK five times to close all open dialog boxes.Clear the selected Model when the selected Make changes:Double-click the Make drop-down list box.In the Drop-Down List Box Properties dialog box, click Rules, and then click Add.Name the rule Clear Model, and then click Add Action.In the Action dialog box, select Set A Field's Value from the Action drop-down list.Click the Select XPath button to the right of the Field text box, and then select myFields/Vehicle/Model in the Main data source.Click OK five times to close all open dialog boxes.Try it:You have now created a three-level cascading list that filters for unique values and prevents invalid selection combinations. Preview the form and try various selection combinations.©2005 Greg Collins. All rights reserved. Licensed to Autonomy Systems, LLC for display on InfoPathDev.com. Posted Jul 06 2005, 07:49 AM by Greg Collins with 6 comment(s) Filed under: Filters, Secondary Data Sources, Lists, Cascading Copyright © 2003-2019 Qdabra Software. All rights reserved.View our Terms of Use.
It is common to need two or more list boxes where the choices in one are dependant on the value of another. This is known as a cascading list. A cascade can occur with as few as two levels up to any number of levels. Some common scenarios which require cascading lists are:
As the number of levels in the cascade increases, so does the complexity of the process and work involved. Also, if the cascading list is presented inside of a repeating table or repeating section you must account for another issue: data crossover. Data crossover means that the options presented in a cascade on a given row will be affected by earlier selected values from other rows—thus destroying the true cascading effect.
In this task we will create a hierarchical secondary data source containing the values used to populate our lists. We will then create a three-level repeating cascading list using drop-down list boxes. We create three levels of cascade to reveal the compounding complexity involved for level three and beyond. We will resolve the issue regarding data crossover using the current function. And finally, we ensure valid selection combinations by clearing selected list values as selections earlier in the cascade are changed.
THE HIERARCHICAL SECONDARY DATA SOURCE
Hierarchical data sources are commonly created for use in XML, and are typically more structured and organized than a flat data source. There are numerous ways to organize the hierarchy; we have arbitrarily chosen a structure that suits this task. The hierarchical structure normally ensures that only unique values appear each list. If, however, you find that filtering for unique values is still needed, refer to Display Only Unique Options in a List. Let's start by creating the hierarchical secondary data source.
Create the hierarchical secondary data source:
Copy the following code into a text editor, and then save the file as Vehicles - Hierarchical Data Source.xml. This file will be used as a secondary data source in our form.
<?xml version="1.0" encoding="UTF-8"?><Vehicles> <Year value="1963"> <Make value="Chevrolet"> <Model value="Corvette"/> <Model value="Nova"/> </Make> <Make value="Porsche"> <Model value="356"/> <Model value="Carrera"/> </Make> </Year> <Year value="1973"> <Make value="Ford"> <Model value="Bronco"/> <Model value="Mustang"/> <Model value="Pinto"/> </Make> <Make value="Toyota"> <Model value="Celica"/> <Model value="Land Cruiser"/> </Make> </Year> <Year value="1979"> <Make value="Jaguar"> <Model value="XJ6"/> </Make> <Make value="Pontiac"> <Model value="Trans Am"/> </Make> <Make value="Volvo"> <Model value="240"/> <Model value="244DL"/> </Make> </Year> <Year value="1987"> <Make value="Dodge"> <Model value="Ram Charger"/> <Model value="Grand Caravan"/> </Make> <Make value="Honda"> <Model value="Civic"/> <Model value="Prelude"/> </Make> <Make value="Nissan"> <Model value="300ZX"/> <Model value="Pulsar"/> <Model value="Sentra"/> </Make> </Year> <Year value="1999"> <Make value="GMC"> <Model value="Jimmy"/> <Model value="Sierra 2500 HD"/> <Model value="Yukon"/> </Make> <Make value="Honda"> <Model value="Passport"/> <Model value="Prelude"/> <Model value="CR-V"/> </Make> <Make value="Jeep"> <Model value="Cherokee"/> </Make> <Make value="Mercury"> <Model value="Grand Marquis"/> <Model value="Sable"/> <Model value="Villager"/> </Make> <Make value="Pontiac"> <Model value="Firebird"/> <Model value="Montana"/> <Model value="Sunfire"/> </Make> </Year> <Year value="2003"> <Make value="Dodge"> <Model value="Dakota"/> <Model value="Caravan"/> <Model value="Ram Charger"/> <Model value="Viper"/> </Make> <Make value="Mercury"> <Model value="Sable"/> </Make> </Year> <Year value="2004"> <Make value="Dodge"> <Model value="Stratus"/> <Model value="Viper"/> </Make> <Make value="Ford"> <Model value="Crown Victoria"/> <Model value="F250"/> <Model value="Thunderbird"/> </Make> <Make value="GMC"> <Model value="Sierra 3500"/> </Make> <Make value="Jeep"> <Model value="Grand Cherokee"/> <Model value="Liberty"/> </Make> </Year></Vehicles>
THE FORM
Now that we have our hierarchical secondary data source we are ready to create our form. First we will design a simple schema to support a three-level repeating cascading list. Then we will design the layout using drop-down list boxes in a repeating table. When the layout is complete we will focus on creating the repeating cascade.
Add the secondary data source to a form:
Create the schema:
Design the view:
Figure 1. Layout of the repeating cascading drop-down list boxes.
THE CASCADING LISTS
With the form layout complete we will now turn our attention to the meat of the task: making one repeating list cascade off of another. The process is not very difficult, but can become increasingly complex as the number of cascade levels increases. Creating a cascade requires the use of filters. The options displayed in one list box are filtered based on values selected in earlier list boxes. Because our cascade is in a repeating structure, we must use the current function to ensure the filter does not crossover to values in other rows. Let's populate each drop-down list box using our secondary data source and create the cascade filters.
Populate the Year drop-down list:
Populate the Make drop-down list:
Filter the Make drop-down list based on the selected Year in the current row:
current()/my:Year
Figure 2. Filtering to compare the Year to the value on the current row.
We mentioned you would encounter the issue of data crossover. An example of data crossover is shown in the difference between Figure 3 and 4. Without using the current function the vehicle make will be filtered on all years currently selected in the repeating table, presenting the user with invalid choice combinations. Thus if you have 3 rows with the years 1963, 1979 and 2004 selected, each of the Make drop-down lists will contain a list of makes for all three of those selected years, as shown in Figure 4. By properly using the current function, we avoid data crossover by limiting the choices in the Make drop-down list to only those of the selected Year on the same row, as shown in Figure 3.
Figure 3. Vehicle makes filtered by year using the current function.
Figure 4. Vehicle makes filtered by year without using the current function.
At this point you have created a two-level repeating cascade. The options in the Make drop-down list are filtered based on the selected Year in the current row. You can test this by previewing your form. Now let's create the level-three repeating cascade, which will reveal the compounding complexity involved in creating each additional level of cascade from here.
Populate the Model drop-down list:
Filter the Model drop-down list based on the selected Year in the current row:
Filter the Model drop-down list based on the selected Make in the current row:
current()/my:Make
Figure 5. Filtering the third level of a repeating cascading list.
You have now created a three-level repeating cascade. Preview the form and test the functionality of the drop-down list boxes. You may discover an issue: you can create invalid selection combinations. We will resolve this issue in the next section.
CLEARING SELECTIONS AFTER CHANGES
One issue with cascading lists that needs to be addressed is that when a selection is changed in an earlier level the selections following that change are likely to be invalid. For example, if you select year 1963 and model Chevrolet, and then select year 1973, Chevrolet remains the selected model, even though our data source does not list it as a model for 1973. The old value needs to be cleared so that invalid selection combinations cannot exist. This can be easily corrected with Rules.
With some extra work, you can probably determine whether the following selected values are still valid and clear only invalid ones, but there are advantages to just clearing each following selected value. One advantage is that rules can cascade as well—like a Domino effect. As one value is changed, the next value is cleared; clearing that value triggers the next value to clear, and so on. Rules automatically affect the current row, so there is no need to filter using the current function in the rule.
The rules we create will have no condition so that they will be processed every time the selected value changes. To clear the selected value of a field, we leave the Value text box of the rule blank.
Clear the selected Make when the selected Year changes:
Clear the selected Model when the selected Make changes:
Try it:
You have now created a three-level repeating cascading list that prevents invalid selection combinations. Preview the form and try various selection combinations.
©2005 Greg Collins. All rights reserved. Licensed to Autonomy Systems, LLC for display on InfoPathDev.com.
In this task we will create a flat secondary data source containing the values used to populate our lists. We will then create a three-level repeating cascading list using drop-down list boxes. We create three levels of cascade to reveal the compounding complexity involved for level three and beyond. Because of the nature of the flat data source, we will filter each list to ensure that only unique values are displayed. We will resolve the issue regarding data crossover using the current function. And finally, we ensure valid selection combinations by clearing selected list values as selections earlier in the cascade are changed.
THE FLAT SECONDARY DATA SOURCE
Flat data sources are commonly returned from databases, Web services, and SharePoint. A flat data source has no hierarchy in the structure; it is simply a list of identical elements, each with an identical set of attributes. Only the values of the attributes change. Flat data sources also require additional filtering to ensure that only unique values appear in the drop-down lists. Let's start by creating the flat secondary data source.
Create the flat secondary data source:
Copy the following code into a text editor, and then save the file as Vehicles - Flat Data Source.xml. This file will be used as a secondary data source in our form.
<?xml version="1.0" encoding="UTF-8"?><Vehicles> <Vehicle year="1963" make="Chevrolet" model="Corvette"/> <Vehicle year="1963" make="Chevrolet" model="Nova"/> <Vehicle year="1963" make="Porsche" model="356"/> <Vehicle year="1963" make="Porsche" model="Carrera"/> <Vehicle year="1973" make="Ford" model="Bronco"/> <Vehicle year="1973" make="Ford" model="Mustang"/> <Vehicle year="1973" make="Ford" model="Pinto"/> <Vehicle year="1973" make="Toyota" model="Celica"/> <Vehicle year="1973" make="Toyota" model="Land Cruiser"/> <Vehicle year="1979" make="Jaguar" model="XJ6"/> <Vehicle year="1979" make="Pontiac" model="Trans Am"/> <Vehicle year="1979" make="Volvo" model="240"/> <Vehicle year="1979" make="Volvo" model="244DL"/> <Vehicle year="1987" make="Dodge" model="Ram Charger"/> <Vehicle year="1987" make="Dodge" model="Grand Caravan"/> <Vehicle year="1987" make="Honda" model="Civic"/> <Vehicle year="1987" make="Honda" model="Prelude"/> <Vehicle year="1987" make="Nissan" model="300ZX"/> <Vehicle year="1987" make="Nissan" model="Pulsar"/> <Vehicle year="1987" make="Nissan" model="Sentra"/> <Vehicle year="1999" make="GMC" model="Jimmy"/> <Vehicle year="1999" make="GMC" model="Sierra 2500 HD"/> <Vehicle year="1999" make="GMC" model="Yukon"/> <Vehicle year="1999" make="Honda" model="Passport"/> <Vehicle year="1999" make="Honda" model="Prelude"/> <Vehicle year="1999" make="Honda" model="CR-V"/> <Vehicle year="1999" make="Jeep" model="Cherokee"/> <Vehicle year="1999" make="Mercury" model="Grand Marquis"/> <Vehicle year="1999" make="Mercury" model="Sable"/> <Vehicle year="1999" make="Mercury" model="Villager"/> <Vehicle year="1999" make="Pontiac" model="Firebird"/> <Vehicle year="1999" make="Pontiac" model="Montana"/> <Vehicle year="1999" make="Pontiac" model="Sunfire"/> <Vehicle year="2003" make="Dodge" model="Dakota"/> <Vehicle year="2003" make="Dodge" model="Caravan"/> <Vehicle year="2003" make="Dodge" model="Ram Charger"/> <Vehicle year="2003" make="Dodge" model="Viper"/> <Vehicle year="2003" make="Mercury" model="Sable"/> <Vehicle year="2004" make="Dodge" model="Stratus"/> <Vehicle year="2004" make="Dodge" model="Viper"/> <Vehicle year="2004" make="Ford" model="Crown Victoria"/> <Vehicle year="2004" make="Ford" model="F250"/> <Vehicle year="2004" make="Ford" model="Thunderbird"/> <Vehicle year="2004" make="GMC" model="Sierra 3500"/> <Vehicle year="2004" make="Jeep" model="Grand Cherokee"/> <Vehicle year="2004" make="Jeep" model="Liberty"/></Vehicles>
Now that we have our flat secondary data source we are ready to create our form. First we will design a simple schema to support a three-level repeating cascading list. Then we will design the layout using drop-down list boxes in a repeating table. When the layout is complete we will focus on creating the repeating cascade.
With the form layout complete we will now turn our attention to the meat of the task: making one list cascade off of another. The process is not very difficult, but can become increasingly complex as the number of cascade levels increases. Creating a cascade requires the use of filters. The options displayed in one list box are filtered based on values selected in earlier list boxes. Because our cascade is in a repeating structure, we must use the current function to ensure the filter does not crossover to values in other rows. Let's populate each drop-down list box using our secondary data source and create the cascade filters.
We mentioned you would encounter the issue of data crossover. An example of data crossover is shown in the difference between Figure 3 and 4 (please note that Figures 3 and 4 already account for unique value filtering). Without using the current function the vehicle make will be filtered on all years currently selected in the repeating table, presenting the user with invalid choice combinations. Thus if you have 3 rows with the years 1963, 1979 and 2004 selected, each of the Make drop-down lists will contain a list of makes for all three of those selected years, as shown in Figure 4. By properly using the current function, we avoid data crossover by limiting the choices in the Make drop-down list to only those of the selected Year on the same row, as shown in Figure 3.
At this point you have created a two-level repeating cascade. The options in the Make drop-down list are filtered based on the selected Year in the current row. You can test this by previewing your form. You will notice that each drop-down list contains repeated values. This is a byproduct of using a flat data source and will be corrected in the next section when we filter for unique values. Now let's create the level-three cascade, which will reveal the compounding complexity involved in creating each additional level of cascade from here.
You have now created a three-level repeating cascade. Preview the form and test the functionality of the drop-down list boxes. You may discover two issues: first, the list options are not unique, and second, you can create invalid selection combinations. We will resolve these two issues in the next two sections.
FILTERING LISTS FOR UNIQUE VALUES
Values in flat data sources are usually repeated. Although this is important given the XML structure, it can lead to option bloat in your list box. It can only serve to confuse and frustrate the user to present them with numerous identical options. The answer is to filter the list to display only unique values. This can be done using XPath.
It should be mentioned that just as the complexity of the cascade filters compounded with each additional cascade level, so do the complexity of the uniqueness filters. You will see this in the expression used to filter the Model drop-down list for unique values.
Add a uniqueness filter to the Year drop-down list:
not(. = ../preceding-sibling::Vehicle/@year)
Figure 6. Filtering list options to display only unique values.
Add a uniqueness filter to the Make drop-down list:
At each cascade level beyond the initial list box, your uniqueness filter must take into consideration the selection from each of the previous levels. Due to the nature of this filter, if you do not take the previous selections into consideration, you may inadvertently completely filter out all valid options.
For example, in our sample secondary data source, vehicle years 1987 and 1999 both include the Honda make. If we did not account for the selected year, the Honda make would not appear as an option when year 1999 was selected. This is because the filter would identify that the Honda make appeared earlier in the secondary data source. The Dodge make in years 2003 and 2004 would also be completely filtered out because Dodge appears earlier, in year 1987. There are a few other makes and models in the sample secondary data source that would encounter this issue.
not(. = ../preceding-sibling::Vehicle[@year = current()/my:Year]/@make)
Note that compared with the uniqueness filter we placed on the Year drop-down list box, there is an additional subfilter specified on the Vehicle node. The subfilter [@year = current()/my:Year] constrains the main filter to verify that we display unique values for each make within the selected year.
Add a uniqueness filter to the Model drop-down list:
not(. = ../preceding-sibling::Vehicle[@year = current()/my:Year and @make = current()/my:Make]/@model)
Just as we did with the uniqueness filter for the Make drop-down list above, here we have added an additional subfilter to guarantee that we are only eliminating repeated options from the list of models within the selected year and selected make.
If you can guarantee that the values, at any level of cascade, will always and forever be unique then you do not need to add the uniqueness filter. If, however, there is any doubt, it is always safer to add it. For more information on filtering lists for unique values, refer to Display Only Unique Options in a List.
You have now created a three-level repeating cascading list that filters for unique values and prevents invalid selection combinations. Preview the form and try various selection combinations.
As the number of levels in the cascade increases, so does the complexity of the process and work involved. Also, if the cascading list is presented inside of a repeating table or repeating section you must account for another issue: data crossover. Repeating cascading lists are covered in Create a Repeating Cascading List from a Flat Data Source and Create a Repeating Cascading List from a Hierarchical Data Source.
In this task we will create a hierarchical secondary data source containing the values used to populate our lists. We will then create a three-level non-repeating cascading list using drop-down list boxes. We create three levels of cascade to reveal the compounding complexity involved for level three and beyond. And finally, we ensure valid selection combinations by clearing selected list values as selections earlier in the cascade are changed.
Now that we have our hierarchical secondary data source we are ready to create our form. First we will design a simple schema to support a three-level cascading list. Then we will design the layout using drop-down list boxes. When the layout is complete we will focus on creating the cascade.
Figure 1. Layout of the cascading drop-down list boxes.
With the form layout complete we will now turn our attention to the meat of the task: making one list cascade off of another. The process is not very difficult, but can become increasingly complex as the number of cascade levels increases. Creating a cascade requires the use of filters. The options displayed in one list box are filtered based on values selected in earlier list boxes. Let's populate each drop-down list box using our secondary data source and create the cascade filters.
Filter the Make drop-down list based on the selected Year:
Figure 2. Filtering the second level of a cascading list.
At this point you have created a two-level cascade. The options in the Make drop-down list are filtered based on the selected Year. You can test this by previewing your form. Now let's create the level-three cascade, which will reveal the compounding complexity involved in creating each additional level of cascade from here.
Filter the Model drop-down list based on the selected Year:
Filter the Model drop-down list based on the selected Make:
Figure 3. Filtering the third level of a cascading list.
You have now created a three-level cascade. Preview the form and test the functionality of the drop-down list boxes. You may discover an issue: you can create invalid selection combinations. We will resolve this issue in the next section.
With some extra work, you can probably determine whether the following selected values are still valid and clear only invalid ones, but there are advantages to just clearing each following selected value. One advantage is that rules can cascade as well—like a Domino effect. As one value is changed, the next value is cleared; clearing that value triggers the next value to clear, and so on.
You have now created a three-level cascading list that prevents invalid selection combinations. Preview the form and try various selection combinations.
In this task we will create a flat secondary data source containing the values used to populate our lists. We will then create a three-level non-repeating cascading list using drop-down list boxes. We create three levels of cascade to reveal the compounding complexity involved for level three and beyond. Because of the nature of the flat data source, we will filter each list to ensure that only unique values are displayed. And finally, we ensure valid selection combinations by clearing selected list values as selections earlier in the cascade are changed.
Now that we have our flat secondary data source we are ready to create our form. First we will design a simple schema to support a three-level cascading list. Then we will design the layout using drop-down list boxes. When the layout is complete we will focus on creating the cascade.
With the form layout complete we will now turn our attention to the meat of the task: making one list cascade off of another. The process is not very difficult, but can become increasingly complex as the number of cascade levels increases. Creating a cascade requires the use of filters. The options displayed in one list box are filtered based on the values selected in earlier list boxes. Let's populate each drop-down list box using our secondary data source and create the cascade filters.
You have now created a three-level cascade. Preview the form and test the functionality of the drop-down list boxes. You may discover two issues: first, the list options are not unique, and second, you can create invalid selection combinations. These two issues will be resolved in the next two sections.
It should be mentioned that just as the complexity of the cascading filters compounded with each additional cascading level, so does the complexity of the uniqueness filters. You will see this in the expression used to filter the Model drop-down list for unique values.
Figure 4. Filtering list options to display only unique values.
For example, in our sample secondary data source, vehicle years 1987 and 1999 both include the Honda make. If we did not account for the selected year, the Honda make would not appear as an option when year 1999 was selected. This is because the filter would identify that the Honda make appeared earlier in the secondary data source. The Dodge make in years 2003 and 2004 would also be completely filtered out because Dodge appears earlier in year 1987. There are a few other makes and models in the sample secondary data source that would encounter this issue.
not(. = ../preceding-sibling::Vehicle[@year = current()/my:Vehicle/my:Year]/@make)
Note that compared with the uniqueness filter we placed on the Year drop-down list box, there is an additional subfilter specified on the Vehicle node. The subfilter [@year = current()/my:Vehicle/my:Year] constrains the main filter to verify that we display unique values for each make within the selected year.
not(. = ../preceding-sibling::Vehicle[@year = current()/my:Vehicle/my:Year and @make = current()/my:Vehicle/my:Make]/@model)
You have now created a three-level cascading list that filters for unique values and prevents invalid selection combinations. Preview the form and try various selection combinations.