Dynamically Selecting a Template
A powerful benefit of using control templates is that you can cause a template to be selected dynamically, depending on the runtime situation. For example, a different template can be selected according to user input or according to the device's environment or settings.
In our example file Cities4-DynamicSelection.mtd, a horizontal or vertical template is selected according to the orientation of the mobile device (landscape or portrait). If the device is held in landscape orientation, then horizontal radio buttons are displayed automatically. If the user changes the device's orientation to portrait, then the display of radio buttons is automatically changed to a vertical display. This design feature has been added to the previous example, Cities3-DynamicUpdates.mtd.
Note: | You can try out this example by turning the device (between landscape and portrait orientations) while the solution is running or by simulating a change of device orientation. To simulate a change of orientation while a simulation is running, click the Change Orientation toolbar button (see screenshot below). |
The screenshot above shows a simulation of Cities4-DynamicSelection.mtd in landscape orientation. In it, the control template Dynamic Radio Buttons (Horizontal) has been automatically selected (because of the landscape orientation) for both sets of radio buttons, and, as a result, the device automatically displays radio buttons horizontally.
Note: | The device orientation is known to us because it is stored in the two MobileTogether variables $MT_Landscape and $MT_Portrait (each of which have a value of either true() or false()). |
How it works
In order to dynamically select templates, we need, in each Placeholder Control, to define two settings:
•an XPath expression to specify the conditions under which the alternative templates are respectively selected (the relevant property is highlighted in the Styles & Properties Pane in the screenshot below)
•an XPath expression to pass parameter values to the selected control template
Selecting the control template
The XPath expression for the placeholder that instantiates radio buttons for countries is:
if ($MT_Landscape)
then 'Dynamic Radio Buttons (Horizontal)'
else 'Dynamic Radio Buttons (Vertical)'
This expression specifies that if the $MT_Landscape global variable has a value of true(), then the control template named Dynamic Radio Buttons (Horizontal) must be used, otherwise (when $MT_Landscape=false()) the control template named Dynamic Radio Buttons (Vertical) must be used. Remember that this expression must evaluate to the name of the control template to be called, which it now does for each orientation (landscape and portrait).
The XPath expression for the placeholder that instantiates radio buttons for cities is slightly different. Since some countries display a large number of cities (Italy 9 and USA 12), all cities of such countries might not be able to be displayed horizontally in a single screen width, even in landscape orientation. So we have restricted the selection of the horizontal template (in landscape orientation) to only those countries having less than 9 cities. The XPath expression is listed below, with the part that counts the number of cities of the selected country being highlighted in yellow.
if ($MT_Landscape and
count($COUNTRIES-AND-CITIES/Cities/Continent[@name=$PERSISTENT/Root/@Continent ]/Country[@name = $PERSISTENT/Root/@Country]/City/@name) lt 9)
then 'Dynamic Radio Buttons (Horizontal)'
else 'Dynamic Radio Buttons (Vertical)'
The effect of the definitions listed above is that: (i) in landscape orientation, all lists of countries are horizontal, whereas in portrait orientation they are all vertical; (ii) in landscape orientation, lists of 1 to 8 cities are displayed horizontally while lists containing more than 8 cities are displayed vertically; in portrait orientation all city lists are displayed vertical.
Defining the parameter values to pass to templates
The XPath expression to pass values to the parameters of the selected control template (see screenshot below) must be either an array expression or a map expression. Bear in mind that you do not know which template will actually be called at runtime. However, you do know that the choice is between two templates and that they both happen to have two parameters with the exact same names. Because both parameters have the same name, the XPath expression to assign values is simpler.
For the first placeholder, we have used an array expression (listed below). The array must consist of two sequences (because we have two parameters), with the first sequence (highlighted in yellow below) providing the value of the first parameter and the second sequence (highlighted in blue) providing the value of the second parameter. The first sequence generates the value of the $values parameter and will evaluate to a list of countries of the selected continent. The second sequence generates the value of the $sort parameter and will evaluate to true() or false(). Note that the order of the sequences in the array must correspond to the order of the parameter definitions in the project, and must include values for any optional parameters—which can be the empty sequence () if no value is needed.
[
($COUNTRIES-AND-CITIES/Cities/Continent[@name=$PERSISTENT/Root/@Continent]/Country/@name),
(if ($PERSISTENT/Root/@SortCountries=1) then true() else false())
]
For the second placeholder, we have used a map expression (listed below). The map must consist of key:value pairs, where the key must be the name of the parameter. The key:value pairs can be supplied in any order.
map{
"values":($COUNTRIES-AND-CITIES/Cities/Continent[@name=$PERSISTENT/Root/@Continent ]/Country[@name = $PERSISTENT/Root/@Country]/City/@name),
"sort":if ($PERSISTENT/Root/@SortCities=1) then true() else false()
}