How to use:
A customized Control Template is used to override the default Style of the Legend Control. Click the 'Customized Layer info' button to see various pieces of information about a Layer. The ToolTip for the Layer that is normally displayed in the Legend in the MapLayerTemplate was disabled.
The XAML code in this example is used in conjunction with the code-behind (C# or VB.NET) to demonstrate the functionality.
The following screen shot corresponds to the code example in this page.
SPECIAL INSTRUCTIONS: This code example uses two Silverlight/WPF/Windows Phone pages. The first page should be named 'TheInfo.xaml' (with corresponding .vb and .cs code-behind files). The second page can use whatever name you choose. Follow these instructions:
First: Add the Silverlight/WPF/Windows Phone page named 'TheInfo.xaml' into your Visual Studio project. Replace the full contents of the code-behind with the provided example code (depending on your programming language). Note: there is no need to modify the .xaml file.
Second: Add another Silverlight/WPF/Windows Phone page. Name it whatever you want. The .xaml and corresponding code-behind (.cs or .vb) will be the main driver for the application sample code.
C# | Copy Code |
---|---|
// This file is the 'TheInfo.xaml.cs' file! using System; public partial class TheInfo : Page { public TheInfo() { InitializeComponent(); } // Create several Properties (with Dependency Properties) that will be used to hold information about a Layer. // The purpose of this Class is to store information via Binding in XAML to an Object. Then pass that Object // to the code-behind so that you can get access to all of the information. public string MyCopyrightText { get { return (string)GetValue(MyCopyrightTextProperty); } set { SetValue(MyCopyrightTextProperty, value); } } public static readonly DependencyProperty MyCopyrightTextProperty = DependencyProperty.Register("MyCopyrightText", typeof(string), typeof(TheInfo), new PropertyMetadata(null)); public string MyUrl { get { return (string)GetValue(MyUrlProperty); } set { SetValue(MyUrlProperty, value); } } public static readonly DependencyProperty MyUrlProperty = DependencyProperty.Register("MyUrl", typeof(string), typeof(TheInfo), new PropertyMetadata(null)); public string MyIsVisible { get { return (string)GetValue(MyIsVisibleProperty); } set { SetValue(MyIsVisibleProperty, value); } } public static readonly DependencyProperty MyIsVisibleProperty = DependencyProperty.Register("MyIsVisible", typeof(string), typeof(TheInfo), new PropertyMetadata(null)); public Collections.ObjectModel.ObservableCollection<ESRI.ArcGIS.Client.Toolkit.Primitives.LayerItemViewModel> MyLayerItems { get { return GetValue(MyLayerItemsProperty); } set { SetValue(MyLayerItemsProperty, value); } } public static readonly DependencyProperty MyLayerItemsProperty = DependencyProperty.Register("MyLayerItems", typeof(Collections.ObjectModel.ObservableCollection<ESRI.ArcGIS.Client.Toolkit.Primitives.LayerItemViewModel>), typeof(TheInfo), new PropertyMetadata(null)); } |
VB.NET | Copy Code |
---|---|
' This file is the 'TheInfo.xaml.vb' file! Partial Public Class TheInfo Inherits Page Public Sub New() InitializeComponent() End Sub ' Create several Properties (with Dependency Properties) that will be used to hold information about a Layer. ' The purpose of this Class is to store information via Binding in XAML to an Object. Then pass that Object ' to the code-behind so that you can get access to all of the information. Public Property MyCopyrightText() As String Get Return CStr(GetValue(MyCopyrightTextProperty)) End Get Set(ByVal value As String) SetValue(MyCopyrightTextProperty, value) End Set End Property Public Shared ReadOnly MyCopyrightTextProperty As DependencyProperty = DependencyProperty.Register("MyCopyrightText", GetType(String), GetType(TheInfo), New PropertyMetadata(Nothing)) Public Property MyUrl() As String Get Return CStr(GetValue(MyUrlProperty)) End Get Set(ByVal value As String) SetValue(MyUrlProperty, value) End Set End Property Public Shared ReadOnly MyUrlProperty As DependencyProperty = DependencyProperty.Register("MyUrl", GetType(String), GetType(TheInfo), New PropertyMetadata(Nothing)) Public Property MyIsVisible() As String Get Return CStr(GetValue(MyIsVisibleProperty)) End Get Set(ByVal value As String) SetValue(MyIsVisibleProperty, value) End Set End Property Public Shared ReadOnly MyIsVisibleProperty As DependencyProperty = DependencyProperty.Register("MyIsVisible", GetType(String), GetType(TheInfo), New PropertyMetadata(Nothing)) Public Property MyLayerItems() As Collections.ObjectModel.ObservableCollection(Of ESRI.ArcGIS.Client.Toolkit.Primitives.LayerItemViewModel) Get Return GetValue(MyLayerItemsProperty) End Get Set(ByVal value As Collections.ObjectModel.ObservableCollection(Of ESRI.ArcGIS.Client.Toolkit.Primitives.LayerItemViewModel)) SetValue(MyLayerItemsProperty, value) End Set End Property Public Shared ReadOnly MyLayerItemsProperty As DependencyProperty = DependencyProperty.Register("MyLayerItems", GetType(Collections.ObjectModel.ObservableCollection(Of ESRI.ArcGIS.Client.Toolkit.Primitives.LayerItemViewModel)), GetType(TheInfo), New PropertyMetadata(Nothing)) End Class |
XAML | Copy Code |
---|---|
<Grid x:Name="LayoutRoot"> <!-- Use the Resources section to hold a Style for setting the appearance and behavior of the Legend Control. Don't forget to add following XAML Namespace definitions to the correct location in your code: xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:esri="http://schemas.esri.com/arcgis/client/2009" xmlns:esriToolkitPrimitives="clr-namespace:ESRI.ArcGIS.Client.Toolkit.Primitives;assembly=ESRI.ArcGIS.Client.Toolkit" xmlns:local="clr-namespace:TestLegend" NOTE: You will need to modify your code for the XAML Namespace definition for using local resources of (xmlns:local="clr-namespace:TestLegend") to match the name of your Project file. For example if your project was called 'BillyBob', the XAML Namespace definition would need to be changed to: xmlns:local="clr-namespace:BillyBob" --> <Grid.Resources> <!-- The majority of the XAML that defines the ControlTemplate for the Legend Control was obtained by using Microsoft Blend. See the blog post entitled: 'Use control templates to customize the look and feel of ArcGIS controls' at the following Url for general How-To background: http://blogs.esri.com/Dev/blogs/silverlightwpf/archive/2010/05/20/Use-control-templates-to-customize-the-look-and-feel-of-ArcGIS-controls.aspx --> <Style x:Key="LegendStyle1" TargetType="esri:Legend"> <Setter Property="Foreground" Value="Black"/> <Setter Property="Background"> <Setter.Value> <!-- Change the default visual appearance of the Legend Control. Rather going from a White to Gray Background (top to bottom), mix things up by going from a Green to Yellow to Magenta Background. --> <LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0"> <GradientStop Color="Green" Offset="0"/> <GradientStop Color="GreenYellow" Offset="0.375"/> <GradientStop Color="Salmon" Offset="0.625"/> <GradientStop Color="Magenta" Offset="1"/> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="BorderBrush"> <Setter.Value> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FFA3AEB9" Offset="0"/> <GradientStop Color="#FF8399A9" Offset="0.375"/> <GradientStop Color="#FF718597" Offset="0.375"/> <GradientStop Color="#FF617584" Offset="1"/> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="VerticalContentAlignment" Value="Top"/> <Setter Property="Cursor" Value="Arrow"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Padding" Value="0"/> <Setter Property="Margin" Value="0"/> <Setter Property="IsTabStop" Value="False"/> <Setter Property="TabNavigation" Value="Once"/> <Setter Property="LayerItemsMode" Value="Flat"/> <Setter Property="LegendItemTemplate"> <Setter.Value> <DataTemplate> <StackPanel Margin="0,-1" Orientation="Horizontal"> <Image HorizontalAlignment="Center" MaxWidth="55" MaxHeight="55" Margin="0,-1" MinWidth="20" Source="{Binding ImageSource}" Stretch="None" VerticalAlignment="Center"/> <TextBlock Margin="5,0,0,0" Text="{Binding Label}" VerticalAlignment="Center"/> </StackPanel> </DataTemplate> </Setter.Value> </Setter> <Setter Property="LayerTemplate"> <Setter.Value> <DataTemplate> <StackPanel Margin="0,-1" Orientation="Horizontal"> <ToolTipService.ToolTip> <StackPanel MaxWidth="400"> <TextBlock FontWeight="Bold" TextWrapping="Wrap" Text="{Binding Layer.ID}"/> <TextBlock FontWeight="Bold" TextWrapping="Wrap" Text="{Binding Label}"/> <TextBlock TextWrapping="Wrap" Text="{Binding Description}"/> <TextBlock Text="{Binding SubLayerID, StringFormat=SubLayer ID : \{0\}}"/> <TextBlock Text="{Binding MinimumResolution, StringFormat=Minimum Resolution : \{0:F6\}}"/> <TextBlock Text="{Binding MaximumResolution, StringFormat=Maximum Resolution : \{0:F6\}}"/> </StackPanel> </ToolTipService.ToolTip> <TextBlock Text="{Binding Label}" VerticalAlignment="Center"/> </StackPanel> </DataTemplate> </Setter.Value> </Setter> <Setter Property="MapLayerTemplate"> <Setter.Value> <DataTemplate> <StackPanel Margin="0,-1"> <StackPanel.Resources> <DataTemplate x:Key="BusyIndicatorTemplate"> <Grid x:Name="BusyIndicator" Background="Transparent" HorizontalAlignment="Left" Margin="3,0" RenderTransformOrigin="0.5,0.5" VerticalAlignment="Center"> <Grid.RenderTransform> <RotateTransform/> </Grid.RenderTransform> <Grid.Triggers> <EventTrigger RoutedEvent="Canvas.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimation Duration="0:0:1" RepeatBehavior="Forever" To="360" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" Storyboard.TargetName="BusyIndicator"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Grid.Triggers> <Ellipse Fill="#1E525252" Height="2" Margin="11,2,11,20" Width="2"/> <Ellipse Fill="#3F525252" HorizontalAlignment="Right" Height="3" Margin="0,4,5,0" VerticalAlignment="Top" Width="3"/> <Ellipse Fill="#7F525252" HorizontalAlignment="Right" Height="4" Margin="0,9,1,0" VerticalAlignment="Top" Width="4"/> <Ellipse Fill="#BF525252" HorizontalAlignment="Right" Height="5" Margin="0,0,3,3" VerticalAlignment="Bottom" Width="5"/> <Ellipse Fill="#FF525252" Height="6" Margin="9,0" VerticalAlignment="Bottom" Width="6"/> </Grid> </DataTemplate> </StackPanel.Resources> <!-- Comment out the default ability to do a ToolTip for the MapLayerTemplate. We will replace with a Button that displays some customized Layer information. --> <!-- <ToolTipService.ToolTip> <StackPanel MaxWidth="400"> <TextBlock FontWeight="Bold" TextWrapping="Wrap" Text="{Binding Layer.CopyrightText}"/> <TextBlock TextWrapping="Wrap" Text="{Binding Description}"/> <TextBlock Text="{Binding MinimumResolution, StringFormat=Minimum Resolution : \{0:F6\}}"/> <TextBlock Text="{Binding MaximumResolution, StringFormat=Maximum Resolution : \{0:F6\}}"/> </StackPanel> </ToolTipService.ToolTip> --> <StackPanel Orientation="Horizontal"> <ContentControl ContentTemplate="{StaticResource BusyIndicatorTemplate}" Visibility="{Binding BusyIndicatorVisibility}"/> <TextBlock FontWeight="Bold" Text="{Binding Label}" VerticalAlignment="Center"/> <!-- IMPORTANT INFORMATION: Add a Button that displays customized Layer information next to the Layer.Label. The key to making this logic work is to add a custom .xaml page (called TheInfo.xaml with the code-behind file TheInfo.xaml.vb/TheInfo.xaml.cs) that contains the ability to set/get some Properties (with Dependency Properties). The 'TheInfo' object is then bound to the Button.Tag Property so that we can use the 'TheInfo' object's information in the code-behind. Remember that you need to add the correct XAML Namespace definition at the top of your XAML code in order to use the local 'TheInfo' object. The binding that is occuring to our custom 'TheInfo' object follows the same pattern that is used in other parts of this Style. For the MapLayerTemplate is it implied that Binding is occuring to the LayerItemViewModel object. --> <local:TheInfo x:Name="MyTheInfo" MyCopyrightText="{Binding Layer.CopyrightText}" MyUrl="{Binding Layer.Url}" MyIsVisible="{Binding IsVisible}" MyLayerItems="{Binding LayerItems}"/> <Button x:Name="TheButton" Content="Customized Layer info" Click="TheButton_Click" Tag="{Binding ElementName=MyTheInfo}"/> </StackPanel> </StackPanel> </DataTemplate> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="esri:Legend"> <esriToolkitPrimitives:TreeViewExtended BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" ItemsSource="{TemplateBinding LayerItemsSource}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"> <esriToolkitPrimitives:TreeViewExtended.ItemTemplate> <sdk:HierarchicalDataTemplate ItemsSource="{Binding LayerItemsSource}"> <ContentPresenter ContentTemplate="{Binding Template}" Content="{Binding}"/> </sdk:HierarchicalDataTemplate> </esriToolkitPrimitives:TreeViewExtended.ItemTemplate> </esriToolkitPrimitives:TreeViewExtended> </ControlTemplate> </Setter.Value> </Setter> </Style> </Grid.Resources> <!-- Add a Map control with a couple of Layers. --> <esri:Map Background="White" HorizontalAlignment="Left" Margin="12,188,0,0" Name="Map1" VerticalAlignment="Top" Height="400" Width="400" > <esri:ArcGISTiledMapServiceLayer ID="Street Map" Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"/> <esri:ArcGISDynamicMapServiceLayer ID="United States" Opacity="0.6" Url="http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer"/> </esri:Map> <!-- Add a Legend Control. Bind the Legend.Map Property to a Map Control. Define the Style of the Legend to use the Control Template that was generated in Blend and modified here in Visual Studio (see above). --> <esri:Legend HorizontalAlignment="Left" Margin="418,188,0,0" Name="Legend1" VerticalAlignment="Top" Width="350" Height="400" Map="{Binding ElementName=Map1}" LayerItemsMode="Tree" Style="{StaticResource LegendStyle1}" /> <!-- Provide the instructions on how to use the sample code. --> <TextBlock Height="70" HorizontalAlignment="Left" Name="TextBlock1" VerticalAlignment="Top" Width="616" TextWrapping="Wrap" Margin="12,12,0,0" Text="A customized Control Template is used to override the default Style of the Legend Control. Click the 'Customized Layer info' button to see various pieces of information about a Layer. The ToolTip for the Layer that is normally displayed in the Legend in the MapLayerTemplate was disabled." /> </Grid> |
C# | Copy Code |
---|---|
private void TheButton_Click(object sender, System.Windows.RoutedEventArgs e) { // This function occurs when the user clicks the Button with the text 'Customized Layer info' next to // each Layer in the Legend. An object based on custom TheInfo Class is passed into this function via // the Button.Tag Property. We extract out information from the TheInfo object to construct an // informational string to display to the user via a MessageBox. // Get the Button.Tag information (i.e. a TheInfo Class object). TheInfo myTheInfo = sender.Tag; // Construct the informational string (using the StringBuilder Class). Text.StringBuilder myDisplayString = new Text.StringBuilder(); // Add information into the StringBuilder. myDisplayString.Append("Selected information about the Layer:" + Environment.NewLine); myDisplayString.Append("Copyright: " + myTheInfo.MyCopyrightText + Environment.NewLine); myDisplayString.Append("Url: " + myTheInfo.MyUrl + Environment.NewLine); myDisplayString.Append("IsVisible: " + myTheInfo.MyIsVisible + Environment.NewLine); // The TheInfo.MyLayerItems Property is a bit more complex that a simple String. It actually contains // the information from the Layer.LayerItems Property. Use this object to display how many sub-Layers // are associated with this particular Layer. Collections.ObjectModel.ObservableCollection<ESRI.ArcGIS.Client.Toolkit.Primitives.LayerItemViewModel> myLayerItems = null; myLayerItems = myTheInfo.MyLayerItems; myDisplayString.Append("Number of sub-Layers: " + myLayerItems.Count.ToString()); // Display the information to the user. MessageBox.Show(myDisplayString.ToString()); } |
VB.NET | Copy Code |
---|---|
Private Sub TheButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) ' This function occurs when the user clicks the Button with the text 'Customized Layer info' next to ' each Layer in the Legend. An object based on custom TheInfo Class is passed into this function via ' the Button.Tag Property. We extract out information from the TheInfo object to construct an ' informational string to display to the user via a MessageBox. ' Get the Button.Tag information (i.e. a TheInfo Class object). Dim myTheInfo As TheInfo = sender.Tag ' Construct the informational string (using the StringBuilder Class). Dim myDisplayString As New Text.StringBuilder ' Add information into the StringBuilder. myDisplayString.Append("Selected information about the Layer:" + vbCrLf) myDisplayString.Append("Copyright: " + myTheInfo.MyCopyrightText + vbCrLf) myDisplayString.Append("Url: " + myTheInfo.MyUrl + vbCrLf) myDisplayString.Append("IsVisible: " + myTheInfo.MyIsVisible + vbCrLf) ' The TheInfo.MyLayerItems Property is a bit more complex that a simple String. It actually contains ' the information from the Layer.LayerItems Property. Use this object to display how many sub-Layers ' are associated with this particular Layer. Dim myLayerItems As Collections.ObjectModel.ObservableCollection(Of ESRI.ArcGIS.Client.Toolkit.Primitives.LayerItemViewModel) myLayerItems = myTheInfo.MyLayerItems myDisplayString.Append("Number of sub-Layers: " + myLayerItems.Count.ToString) ' Display the information to the user. MessageBox.Show(myDisplayString.ToString) End Sub |
Setting this Property is required to have the Legend Control display information about the Layers in the Map.
In the following XAML example, Binding is used to associate a Map Control named 'Map1' to the Legend Control’s Map Property:
<esri:Legend Name="Legend1" Map="{Binding ElementName=Map1}" />
Target Platforms: Windows XP Professional, Windows Server 2003 family, Windows Vista, Windows Server 2008 family