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 API for Windows Phone applications. The Legend control will display information about all or select layers in your map, and honors the visible extent of the layers included.

Screen shot of a basic legend with LayerItemsMode Flat
TipTip:

The symbology associated with a GraphicsLayer will only display 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 code above 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 in XAML using the following properties; default values are listed:

Legend Properties

Description

Map

The map the legend is bound to and will display 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 generated 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 the 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 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, 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 to specify if only layers visible in the map should participate in the Legend.

Default: true.

Creating a tree display

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

<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 code above 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. This toolkit can be downloaded from http://silverlight.codeplex.com/releases/view/36060.
  • 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.
Legend with Silverlight 3 TreeView control

Formatting the Legend control display

Using the XAML above to add a legend to your application will result in a legend that fills the screen. One way to give the legend a better size, along with a nice border, is to wrap it in a Border control:

<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>

In 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. Simply wrapping the control in a ScrollViewer will enable the user to view the entire contents:

<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 will scroll automatically and you do not need to add a ScrollViewer.

Visibility of the Legend control

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

<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="List.png" Text="legend" 
            Click="ApplicationBarIconButton_Click"/>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
Then implement the Click event for the ApplicationBarIconButton in the code-behind:
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, these can be thought of as a hierarchy:

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 will 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, and there is a default MapLayerTemplate. For example, if you wanted to allow users to toggle the visibility of all layers, you could overwrite the default LayerTemplate 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 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. And if it is a LegendItemViewModel, then the LegendItemTemplate is applied. As a result, the properties available to bind to within the template are inherited from the type to which the template is being applied.


12/1/2010