Adding a legend

When looking at a map, it is often helpful to have a legend that provides information about the symbology used. A Legend control is included in the ESRI.ArcGIS.Client.Toolkit assembly for you to use in your ArcGIS Runtime SDK for Windows Phone applications. The Legend control displays information about all or select layers in your map, and honors the visible extent of the layers included. See the following screen shot:

Screen shot of a basic legend with LayerItemsMode Flat
TipTip:

The symbology associated with a GraphicsLayer only displays in the legend if a renderer is applied on the GraphicsLayer.

Using the Legend control

To create a legend for your map, add the Legend control in the XAML, binding it to the map and specifying which layers it should display. The following code shows an example of a simple legend created in XAML:

<esriToolkit:Legend x:Name="Legend"  Map="{Binding ElementName=MyMap}" 
                    LayerIDs="Points of Interest, United States" />
NoteNote:

The preceding code assumes that your application has the following:

  • A map named MyMap
  • Two layers with the IDs "Points of Interest" and "United States"
  • References to the ESRI.ArcGIS.Client and ESRI.ArcGIS.Client.Toolkit assemblies
  • An XML namespace reference, named esriToolkit, to the ESRI.ArcGIS.Client.Toolkit namespace, contained in the assembly of the same name

You can modify the Legend control in XAML using the following properties; default values are listed:

Legend properties

Description

Map

The map the legend is bound to and displays information about. A Legend control must be bound to a map or it will be empty.

LayerIDs

The layer IDs of the layers participating in the legend. It is specified in XAML and in Blend as a comma-delimited string. The order of the layer IDs in the comma-delimited string is used in generating the order the layers are listed in the legend.

TipTip:

If a layer ID contains a comma, use &#44 in place of the comma.

Default: Include all layers in the map.

LayerItemsMode

Specify the structure of the legend: either Flat or Tree. A Flat legend is a list of all the leaves of the layers; a Tree view maintains hierarchical structure of the layers and group layers.

Default: Flat.

CautionCaution:

In Windows Phone, there is no built in TreeView control. When a LayerItemsMode of Tree is used, the Legend control entries are processed as a tree. However, since the default template doesn't know how to display a tree, only the root-level items of the tree display. To create a true Tree in the Legend control, a custom LayerTemplate needs to be provided that contains instructions for displaying content in a tree structure. This is shown in Creating a tree display.

ShowOnlyVisibleLayers

A Boolean value to specify if only layers visible in the map should participate in the legend.

Default: true.

Creating a tree display

As previously mentioned, Windows Phone doesn't have a built in TreeView control, so to create a true tree in the Legend control, a control template needs to be provided that contains instructions for displaying content in a tree structure. Since Windows Phone is based on Silverlight 3, one way to do this is to include the TreeView Microsoft provided as part of the Silverlight 3 Toolkit, and to use that to create a template for the Legend control. See the following code:

<esriToolkit:Legend Map="{Binding ElementName=MyMap}" LayerItemsMode="Tree" 
                    ShowOnlyVisibleLayers="False"
                    LayerIDs="Points of Interest, United States" >
    <esriToolkit:Legend.Template>
        <ControlTemplate TargetType="esriToolkit:Legend">
            <msSL3Toolkit:TreeView 
                ItemsSource="{TemplateBinding LayerItemsSource}"                          
                Background="{StaticResource PhoneBackgroundBrush}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"      
                Padding="{TemplateBinding Padding}"
                HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" 
                Foreground="{StaticResource PhoneForegroundBrush}"
                ItemContainerStyle="{StaticResource TreeViewItemCustomStyle}">
                <msSL3Toolkit:TreeView.ItemTemplate>
                    <msSL3ToolkitCommon:HierarchicalDataTemplate 
                        ItemsSource="{Binding LayerItemsSource}">
                        <ContentPresenter Content="{Binding}" 
                                          ContentTemplate="{Binding Template}" />
                    </msSL3ToolkitCommon:HierarchicalDataTemplate>
                </msSL3Toolkit:TreeView.ItemTemplate>
            </msSL3Toolkit:TreeView>
        </ControlTemplate>
    </esriToolkit:Legend.Template>
</esriToolkit:Legend>
NoteNote:

The preceding code assumes that your application has the following:

  • A map named MyMap
  • Two layers with the IDs "Points of Interest" and "United States"
  • References to the ESRI.ArcGIS.Client and ESRI.ArcGIS.Client.Toolkit assemblies
  • An XML namespace reference, named esriToolkit, to the ESRI.ArcGIS.Client.Toolkit namespace, contained in the assembly of the same name
  • A reference to the System.Windows.Controls assembly that is a part of the Silverlight 3 Toolkit from Microsoft
  • An XML namespace reference, named msSL3Toolkit, to the System.Windows.Controls namespace, contained in the assembly of the same name.
  • An XML namespace reference, named msSL3ToolkitCommon, to the System.Windows namespace, in the System.Windows.Controls assembly.
  • A custom ItemContainerStyle, named TreeViewItemCustomStyle. The style used in this code is based on the default style provided in the toolkit, but is customized to use the phone's brushes, along with larger ToggleButtons. Without these style changes, the TreeView doesn't display well against both the light and dark themes, and the ToggleButtons are hard to select.

See the following screen shot of the legend created with a TreeView:

Legend with Silverlight 3 TreeView control

Formatting the Legend control display

Using the previous XAML code to add a legend to your application results in a legend that fills the screen. One way to give the legend a better size, along with a nice border (as shown in the previous screen shot), is to wrap it in a Border control as shown in the following example:

<Border x:Name="LegendBorder" Background="#77919191" BorderThickness="1" 
        CornerRadius="5" HorizontalAlignment="Right" VerticalAlignment="Top"
        Margin="20" Padding="5" BorderBrush="Black" >
    <esriToolkit:Legend x:Name="Legend" Map="{Binding ElementName=MyMap}"
                        LayerIDs="Points of Interest, United States" 
                        LayerItemsMode="Tree" >
    </esriToolkit:Legend>
</Border>

On a Windows Phone screen, a legend may be too long to fit. By default, only the part that fits onto the screen will be visible. Wrapping the control in a ScrollViewer enables the user to view the entire contents. See the following code:

<Border x:Name="LegendBorder" Background="#77919191" BorderThickness="1" CornerRadius="5"
        HorizontalAlignment="Right"  VerticalAlignment="Top"
        Margin="20" Padding="5" BorderBrush="Black" >
    <ScrollViewer>
        <esriToolkit:Legend x:Name="Legend" Map="{Binding ElementName=MyMap}"
                            LayerIDs="Points of Interest, United States" >
        </esriToolkit:Legend>
    </ScrollViewer>
</Border>
NoteNote:

If you have added a Silverlight 3 TreeView control to your Legend, it scrolls automatically and you do not need to add a ScrollViewer.

Visibility of the legend

Since a Windows Phone has limited screen space, the legend should be easy to turn on and off. Using a button on the ApplicationBar is one way to do so. In the XAML, add the ApplicationBar, including a single button to toggle the LegendBorder's visibility. See the following code:

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="List.png" Text="legend" 
            Click="ApplicationBarIconButton_Click"/>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
Next, implement the Click event for the ApplicationBarIconButton in the code-behind. See the following code:
private void ApplicationBarIconButton_Click(object sender, EventArgs e)
{
    if (LegendBorder.Visibility == System.Windows.Visibility.Visible)
        LegendBorder.Visibility = System.Windows.Visibility.Collapsed;
    else
        LegendBorder.Visibility = System.Windows.Visibility.Visible;
}

Understanding the Legend control's components

The Legend control displays information about data that is shown in the map. As a developer, you add layers to your application's map, and the legend displays information about those layers, including any sub-layers within the service layers if there are any, and the symbology used. To understand the Legend control, these can be thought of as a hierarchy. See the following:

Internally, each of the items in the Legend is a LegendItemViewModel. However, map layers and sub-layers are of type LayerItemViewModel, which is a particular type of LegendItemViewModel, and know whether or not they are a map layer.

Providing a custom LegendItemTemplate, LayerTemplate, or MapLayerTemplate

The legend created in Using the Legend control is basic: it provides a list of the layers and their symbology. If instead you want a legend that is more interactive, or otherwise has a customized look and feel, you need to template the legend. Three templates are supported by the Legend control: LegendItemTemplate, LayerTemplate, and MapLayerTemplate.

The LegendItemTemplate is used at the lowest level in the legend hierarchy, formatting the display of the items on the map. The default template includes an image and a label, providing the symbol and name of a feature in the map.

The LayerTemplate is used for all layer items, including map layers and sub-layers, as defined in the previous section. However, it only applies to map layers if there is no MapLayerTemplate provided. Since there is a default MapLayerTemplate, you must set the MapLayerTemplate to null if you want your LayerTemplate to apply to both map layers and sub-layers. For example, if you wanted to allow users to toggle the visibility of all layers, you could overwrite the default LayerTemplate to provide the visiblity toggle, and set the MapLayerTemplate to null. This is shown in Creating an interactive table of contents. Sub-layers are only present if your Legend includes display of a dynamic map service, so if you have both a MapLayerTemplate and a LayerTemplate, the LayerTemplate will only be used on sub-layers in the dynamic map service.

The MapLayerTemplate is used to customize the map layer items in the Legend, and is an optional template. These templates can be used to interact with the map layers: for example, they can be set up to toggle the map layers on and off, or change the layer opacity. This is shown in detail in the topic Creating an interactive table of contents. In Flat LayerItemsMode, this template won't be applied to dynamic map services since their map layer won't be visible. If you want to use your LayerTemplate for all map layers as well as sublayers, this template must explicitly be set to null: the default is to use the LayerTemplate if there is no MapLayerTemplate, but a default MapLayerTemplate is provided.

Behind the scenes, the Legend contains a list of LegendItemViewModel type, some of which are more specifically of type LayerItemViewModel. If the item is of type LayerItemViewModel, it also knows if it is a map layer or if instead, it is just a sub-layer. When templates are applied, the Legend applies a template to each of the LegendItemViewModels that it contains, and selects the template to apply based on additional information about the legend item: if it is a LayerItemViewModel that is a map layer, and there is a MapLayerTemplate, the MapLayerTemplate is applied. If it is a LayerItemViewModel but not a map layer, or if there is no MapLayerTemplate, the LayerTemplate is applied. If it is a LegendItemViewModel, then the LegendItemTemplate is applied. As a result, the available properties to bind to within the template are inherited from the type to which the template is being applied.

6/21/2013