dot
Identify task

With the Identify task, you can search the layers in a map for features that intersect an input geometry. Once the matching features are returned, you can use .NET code to display their geometries and attributes in your Silverlight application. To use an Identify task, you will need to include code to define the task's user interface and specify its execution logic.

An example of XAML and .NET code (in this case C#) for a simple Silverlight application that includes an Identify task is shown below. This application defines an Identify task that uses the Map control's MouseClick event for specifying the input geometry and executing the task. The list of intersecting features is displayed in a ComboBox. The feature currently selected in the ComboBox has its attributes shown in a DataGrid and its geometry drawn in a GraphicsLayer. The rest of this document will walk you through how the Identify task is defined in the example.

[XAML]

<UserControl x:Class="SilverlightApp.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client"
    xmlns:esriTasks="clr-namespace:ESRI.ArcGIS.Client.Tasks;assembly=ESRI.ArcGIS.Client"
    xmlns:esriSymbols="clr-namespace:ESRI.ArcGIS.Client.Symbols;assembly=ESRI.ArcGIS.Client"
    xmlns:slData="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" >

    <Grid x:Name="LayoutRoot" Background="White" >

        <!-- IDENTIFY TASK RESOURCES -->
        <Grid.Resources>
            <esriSymbols:PictureMarkerSymbol x:Name="IdentifyLocationSymbol" OffsetX="35" OffsetY="35" 
                 Source="/Assets/images/i_about.png" />
            <esriSymbols:SimpleFillSymbol x:Name="SelectedFeatureSymbol" Fill="#64FF0000" BorderBrush="Red" 
                BorderThickness="2" />
        </Grid.Resources>

        <!-- MAP -->
        <esri:Map x:Name="MyMap" Extent="-130,10,-70,60" MouseClick="MyMap_MouseClick" >
            <esri:Map.Layers>
                <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer" 
                      Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"/>
                <esri:GraphicsLayer ID="ResultsGraphicsLayer" />
                <esri:GraphicsLayer ID="IdentifyIconGraphicsLayer" />
            </esri:Map.Layers>
        </esri:Map>

        <!-- IDENTIFY TASK INTERFACE -->
        <StackPanel Margin="10" HorizontalAlignment="Left">
            <Grid>
                <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
                <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                    Margin="10,5,10,5" />
                <StackPanel x:Name="IdentifyResultsStackPanel" Margin="15,25,15,10" Visibility="Collapsed">
                    <TextBlock Text="Select a result from the list to display it" Foreground="White" 
                        FontSize="10" Margin="0,0,0,5" />
                    <ComboBox x:Name="IdentifyComboBox" SelectionChanged="IdentifyComboBox_SelectionChanged" />
                    <ScrollViewer MaxHeight="340" Margin="0,10,0,0">
                        <slData:DataGrid x:Name="IdentifyDetailsDataGrid" AutoGenerateColumns="False" 
                            HeadersVisibility="None" >
                            <slData:DataGrid.Columns>
                                <slData:DataGridTextColumn Binding="{Binding Path=Key}" FontWeight="Bold"/>
                                <slData:DataGridTextColumn Binding="{Binding Path=Value}"/>
                            </slData:DataGrid.Columns>
                        </slData:DataGrid>
                    </ScrollViewer>
                </StackPanel>
            </Grid>
        </StackPanel>
    </Grid>
</UserControl>

[C#]

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Collections.Generic;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Tasks;
using ESRI.ArcGIS.Client.Symbols;

namespace SilverlightApp
{
	public partial class Page : UserControl
	{
		private List<IdentifyResults> _lastIdentifyResult;

		public Page() { InitializeComponent(); }

		// Do identify when Map is clicked
		private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
		{
			// Show an icon at the identify location
			GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
			graphicsLayer.ClearGraphics();
			ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
			{
				Geometry = args.MapPoint,
				Symbol = IdentifyLocationSymbol
			};
			graphicsLayer.Graphics.Add(graphic);

			// Identify task initialization
			IdentifyTask identifyTask = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
				"Demographics/ESRI_Census_USA/MapServer");
			identifyTask.ExecuteCompleted += IdentifyTask_ExecuteCompleted;
			identifyTask.Failed += IdentifyTask_Failed;

			// Initialize Identify parameters. Specify searching of all layers.
			IdentifyParameters identifyParameters = new IdentifyParameters();
			identifyParameters.LayerOption = LayerOption.all;

			// Pass current Map properties to identify parameters
			identifyParameters.MapExtent = MyMap.Extent;
			identifyParameters.Width = (int)MyMap.ActualWidth;
			identifyParameters.Height = (int)MyMap.ActualHeight;

			// Identify features at the click point
			identifyParameters.Geometry = args.MapPoint;

			identifyTask.ExecuteAsync(identifyParameters);
		}

		// Populate ComboBox with results when identify is complete
		private void IdentifyTask_ExecuteCompleted(object sender, IdentifyEventArgs args)
		{
			IdentifyComboBox.Items.Clear();

			// Check for new results
			if (args.IdentifyResults.Count > 0)
			{
				// Show ComboBox and attribuets DataGrid
				IdentifyResultsStackPanel.Visibility = Visibility.Visible;

				// Add results to ComboBox
				foreach (IdentifyResult result in args.IdentifyResults)
				{
					string title = string.Format("{0} ({1})", result.Value.ToString(), result.LayerName);
					IdentifyComboBox.Items.Add(title);
				}

				// Workaround for ComboBox bug
				IdentifyComboBox.UpdateLayout();

				// Store the list of identify results
				_lastIdentifyResult = args.IdentifyResults;

				// Initialize ComboBox and fire SelectionChanged
				IdentifyComboBox.SelectedIndex = 0;
			}
			else
			{
				// Hide ComboBox and attributes DataGrid and notify user
				IdentifyResultsStackPanel.Visibility = Visibility.Collapsed;
				MessageBox.Show("No features found");
			}
		}

		// Show geometry and attributes of selected feature
		void IdentifyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			// Clear previously selected feature from GraphicsLayer
			GraphicsLayer graphicsLayer = MyMap.Layers["ResultsGraphicsLayer"] as GraphicsLayer;
			graphicsLayer.ClearGraphics();

			// Check that ComboBox has a selected item.  Needed because SelectionChanged fires
			// when ComboBox.Clear is called.
			if (IdentifyComboBox.SelectedIndex > -1)
			{
				// Update DataGrid with selected feature's attributes
				Graphic selectedFeature = _lastIdentifyResult[IdentifyComboBox.SelectedIndex].Feature;
				IdentifyDetailsDataGrid.ItemsSource = selectedFeature.Attributes;

				// Apply symbol and add selected feature to map
				selectedFeature.Symbol = SelectedFeatureSymbol;
				graphicsLayer.Graphics.Add(selectedFeature);
			}
		}

		// Notify when identify fails
		private void IdentifyTask_Failed(object sender, TaskFailedEventArgs args)
		{
			MessageBox.Show("Identify failed: " + args.Error);
		}

	}
}

How to create an Identify task

The following steps assume you have created a Silverlight application with a map and a base layer as described in Creating a Map. The XAML view of your application's main page (e.g. Page.xaml) should look similar to the following:

<UserControl x:Class="SilverlightApp.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client">
    
    <Grid x:Name="LayoutRoot" Background="White">
                
        <!-- MAP -->
        <esri:Map x:Name="MyMap" Extent="-130,10,-70,60" >
            <esri:Map.Layers>
                <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer" 
                      Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"/>
            </esri:Map.Layers>
        </esri:Map>
    </Grid>
</UserControl>

The code in the main page's code-behind (e.g. Page.xaml.cs) should be unchanged from when you created your Silverlight application project in Visual Studio.

Creating an input interface for the Identify task

Since tasks do not define a user interface, you must implement an input interface to allow users of your application to perform identify operations. The interface defined by the example can be thought of as three parts:

You will define each of these in the steps below.

  1. In XAML, specify a Rectangle to use as the background for the task's instructions. Place the Rectangle inside a Grid and the Grid inside a StackPanel. This structure - a Rectangle inside a Grid inside a StackPanel - causes the Rectangle to automatically resize to the visible contents of the Grid. This resizing behavior will allow you to also use the Rectangle as the background for the list of results and their attributes.
  2. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
        </Grid>
    </StackPanel>

  3. Define a TextBox to inform the user about how to execute the Identify task.
  4. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
        </Grid>
    </StackPanel>

  5. To use a point as the input geometry for the Identify task, the Map's MouseClick event can be used. This event fires whenever the Map control is clicked. Define the MouseClick attribute within the Map's XAML element as shown below.
  6. <esri:Map x:Name="MyMap" Extent="-130,10,-70,60" MouseClick="MyMap_MouseClick" >
        <esri:Map.Layers>
            <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer" 
                  Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"/>
        </esri:Map.Layers>
    </esri:Map>

  7. To show the user the location of the identify operation, you will display an image at the click point. Images can be displayed on a Map control by using a PictureMarkerSymbol, which is included in the ESRI.ArcGIS.Client.Symbols namespace of the ESRI.ArcGIS.Client assembly. So to use a PictureMarkerSymbol in XAML, you must first add an XML namespace reference to the ESRI.ArcGIS.Client.Symbols namespace.
  8. <UserControl x:Class="SilverlightApp.Page"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client"
        xmlns:esriTasks="clr-namespace:ESRI.ArcGIS.Client.Tasks;assembly=ESRI.ArcGIS.Client"
        xmlns:esriSymbols="clr-namespace:ESRI.ArcGIS.Client.Symbols;assembly=ESRI.ArcGIS.Client" >

  9. Now declare a PictureMarkerSymbol as a resource of the root Grid element.
  10. <Grid.Resources>
        <esriSymbols:PictureMarkerSymbol />
    </Grid.Resources>

  11. Specify the "x:Name" attribute for the symbol. This will allow you to reference the symbol from the page's code-behind.
  12. <Grid.Resources>
        <esriSymbols:PictureMarkerSymbol x:Name="IdentifyLocationSymbol" />
    </Grid.Resources>

  13. Specify the path to the image in the symbol element's Source attribute. Note that you will also have to add this image to your Silverlight Application project in Visual Studio in the location specified. The OffsetX and OffsetY attributes allow you to specify the location of the image relative to the click point. For the image used in this example, define these as shown.
  14. <Grid.Resources>
        <esriSymbols:PictureMarkerSymbol x:Name="IdentifyLocationSymbol" OffsetX="35" OffsetY="35" 
             Source="/Assets/images/i_about.png" />
    </Grid.Resources>

  15. Add a GraphicsLayer to the Map control to use for drawing the PictureMarkerSymbol on the map.
  16. <esri:Map x:Name="MyMap" Extent="-130,10,-70,60" MouseClick="MyMap_MouseClick" >
        <esri:Map.Layers>
            <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer" 
                  Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"/>
            <esri:GraphicsLayer ID="IdentifyIconGraphicsLayer" />
        </esri:Map.Layers>
    </esri:Map>

Creating an output interface for the Identify task

To display the Identify task's results, you need to specify an output interface. Since the result features of an Identify operation will overlap geographically, this example shows you how to implement a ComboBox control that allows users to select a single feature to display. You will define a Silverlight DataGrid to show the selected feature's attributes and a GraphicsLayer to display the selected feature's geometry.

  1. The Rectangle element you defined earlier as the background for the Identify task's instructions will also be used as the background for the ComboBox and DataGrid. Add a StackPanel to the Rectangle's container element to position the ComboBox and DataGrid and control their visibility.
  2. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
            <StackPanel Margin="15,30,15,10">
            </StackPanel>
        </Grid>
    </StackPanel>

  3. Within the StackPanel element, specify the "x:Name" attribute to enable access from the page's code-behind. Define the Visibility attribute as "Collapsed" so that the uninitialized ComboBox and DataGrid are not visible.
  4. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
            <StackPanel x:Name="IdentifyResultsStackPanel" Margin="15,30,15,10" Visibility="Collapsed">
            </StackPanel>
        </Grid>
    </StackPanel>

  5. Add a TextBlock to the StackPanel to instruct the user.
  6. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
            <StackPanel x:Name="IdentifyResultsStackPanel" Margin="15,30,15,10" Visibility="Collapsed">
                <TextBlock Text="Select a result from the list to display it" Foreground="White" 
                    FontSize="10" Margin="0,0,0,5" />
            </StackPanel>
        </Grid>
    </StackPanel>

  7. Define the ComboBox for selecting result features, declaring a handler for the ComboBox's SelectionChanged event. The SelectionChanged event fires when the item selected in the ComboBox changes. Later, you will implement this handler so that it updates the attributes shown in the DataGrid and the result feature drawn on the map.

    <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
            <StackPanel x:Name="IdentifyResultsStackPanel" Margin="15,30,15,10" Visibility="Collapsed">
                <TextBlock Text="Select a result from the list to display it" Foreground="White" 
                    FontSize="10" Margin="0,0,0,5" />
                <ComboBox x:Name="IdentifyComboBox" SelectionChanged="IdentifyComboBox_SelectionChanged" />
            </StackPanel>
        </Grid>
    </StackPanel>

  8. The Silverlight DataGrid is included in the System.Windows.Controls namespace of the System.Windows.Controls.Data assembly. Add an XML namespace that maps to this CLR namespace.
  9. <UserControl x:Class="SilverlightApp.Page"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:esri="clr-namespace:ESRI.ArcGIS.Client;assembly=ESRI.ArcGIS.Client"
        xmlns:esriTasks="clr-namespace:ESRI.ArcGIS.Client.Tasks;assembly=ESRI.ArcGIS.Client"
        xmlns:esriSymbols="clr-namespace:ESRI.ArcGIS.Client.Symbols;assembly=ESRI.ArcGIS.Client"
        xmlns:slData="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" >

  10. Inside the Identify results StackPanel, declare a DataGrid. You will declare the grid's column explicitly, so set the AutoGenerateColumns attribute to false.
  11. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
            <StackPanel x:Name="IdentifyResultsStackPanel" Margin="15,30,15,10" Visibility="Collapsed">
                <TextBlock Text="Select a result from the list to display it" Foreground="White" 
                    FontSize="10" Margin="0,0,0,5" />
                <ComboBox x:Name="IdentifyComboBox" SelectionChanged="IdentifyComboBox_SelectionChanged" />
                <slData:DataGrid x:Name="IdentifyDetailsDataGrid" AutoGenerateColumns="False" >
                </slData:DataGrid>
            </StackPanel>
        </Grid>
    </StackPanel>

  12. In the DataGrid, the attributes will be shown in two columns - one for the attribute field name and the other for the attribute value. Since this format does not use column headers, set the DataGrid's HeaderVisibility to "None."
  13. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
            <StackPanel x:Name="IdentifyResultsStackPanel" Margin="15,30,15,10" Visibility="Collapsed">
                <TextBlock Text="Select a result from the list to display it" Foreground="White" 
                    FontSize="10" Margin="0,0,0,5" />
                <ComboBox x:Name="IdentifyComboBox" SelectionChanged="IdentifyComboBox_SelectionChanged" />
                <slData:DataGrid x:Name="IdentifyDetailsDataGrid" AutoGenerateColumns="False" 
                    HeadersVisibility="None" >
                </slData:DataGrid>
            </StackPanel>
        </Grid>
    </StackPanel>

  14. Add two columns to the DataGrid - one for the field name and one for the attribute value. Specify a bold font for the field name column.
  15. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
            <StackPanel x:Name="IdentifyResultsStackPanel" Margin="15,30,15,10" Visibility="Collapsed">
                <TextBlock Text="Select a result from the list to display it" Foreground="White" 
                    FontSize="10" Margin="0,0,0,5" />
                <ComboBox x:Name="IdentifyComboBox" SelectionChanged="IdentifyComboBox_SelectionChanged" />
                <slData:DataGrid x:Name="IdentifyDetailsDataGrid" AutoGenerateColumns="False" 
                    HeadersVisibility="None" >
                    <slData:DataGrid.Columns>
                        <slData:DataGridTextColumn FontWeight="Bold"/>
                        <slData:DataGridTextColumn />
                    </slData:DataGrid.Columns>
                </slData:DataGrid>
            </StackPanel>
        </Grid>
    </StackPanel>

  16. In the ArcGIS API for Silverlight, result features are returned as Graphic objects, each of which defines its attributes as a Dictionary. In this attribute dictionary, each item's Key is the attribute name and Value is the attribute value. Since data controls in Silverlight can be bound to properties of CLR types, you can show the field name in one column and attribute value in the other by explicitly binding to the Key and Value properties as shown below.
  17. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
            <StackPanel x:Name="IdentifyResultsStackPanel" Margin="15,30,15,10" Visibility="Collapsed">
                <TextBlock Text="Select a result from the list to display it" Foreground="White" 
                    FontSize="10" Margin="0,0,0,5" />
                <ComboBox x:Name="IdentifyComboBox" SelectionChanged="IdentifyComboBox_SelectionChanged" />
                <slData:DataGrid x:Name="IdentifyDetailsDataGrid" AutoGenerateColumns="False" 
                    HeadersVisibility="None" >
                    <slData:DataGrid.Columns>
                        <slData:DataGridTextColumn Binding="{Binding Path=Key}" FontWeight="Bold"/>
                        <slData:DataGridTextColumn Binding="{Binding Path=Value}"/>
                    </slData:DataGrid.Columns>
                </slData:DataGrid>
            </StackPanel>
        </Grid>
    </StackPanel>

  18. Embed the DataGrid in a ScrollViewer element. This will limit the height of the DataGrid, which is desirable in this case because the layers in the ESRI_Census_USA map service contain many attributes.
  19. <StackPanel Margin="10" HorizontalAlignment="Left">
        <Grid>
            <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
            <TextBlock Text="Click the map to identify a feature" Foreground="White" FontSize="10" 
                Margin="10,5,10,5" />
            <StackPanel x:Name="IdentifyResultsStackPanel" Margin="15,30,15,10" Visibility="Collapsed">
                <TextBlock Text="Select a result from the list to display it" Foreground="White" 
                    FontSize="10" Margin="0,0,0,5" />
                <ComboBox x:Name="IdentifyComboBox" SelectionChanged="IdentifyComboBox_SelectionChanged" />
                <ScrollViewer MaxHeight="340" Margin="0,10,0,0">
                    <slData:DataGrid x:Name="IdentifyDetailsDataGrid" AutoGenerateColumns="False" 
                        HeadersVisibility="None" >
                        <slData:DataGrid.Columns>
                            <slData:DataGridTextColumn Binding="{Binding Path=Key}" FontWeight="Bold"/>
                            <slData:DataGridTextColumn Binding="{Binding Path=Value}"/>
                        </slData:DataGrid.Columns>
                    </slData:DataGrid>
                </ScrollViewer>
            </StackPanel>
        </Grid>
    </StackPanel>

Implementing the Identify task's execution logic

Now that you've specified the Identify task's user interface, you need to define its execution logic. This execution logic can be divided into three parts:

You will implement these components in .NET code contained in the main page's code-behind.This code is linked to the XAML presentation layer by manipulating elements that you declared in XAML with "x:Name" or "ID" attributes and implementing methods that you declared in XAML as event handlers. The steps below assume that you are adding code to the Page class in the code-behind file for your Silverlight application's main page (e.g. Page.xaml.cs). In this example, C# is used.

Executing the task

In the application's XAML, you declared the MyMap_MouseClick method as a handler for the Map's MouseClick event. Now you will implement this handler in the page's code-behind. When you are done, the handler will display an icon at the clicked location, instantiate the task and configure its input parameters, and execute the task. The task is declared and initialized in the code-behind because tasks alone do not define any user interface, but rather encapsulate pieces of execution logic. In Silverlight, XAML is reserved for an application's presentation layer, while the code-behind is where business logic is implemented.

  1. Declare the MyMap_MouseClick method.
  2. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {            
    }

  3. Retrieve the GraphicsLayer for the Identify icon and clear it of any previously drawn symbols.
  4. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    }

  5. Instantiate a new Graphic. Set its geometry to be the point clicked on the map and its symbol to be the PictureMarkerSymbol resource that references the Identify icon.
  6. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    }

  7. Add the Identify graphic to the GraphicsLayer.
  8. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    	graphicsLayer.Graphics.Add(graphic);
    }

  9. Declare and instantiate an Identify task. Set the map service that the task will search by passing the service's URL to the Identify task's constructor. To find the URL, you can use the ArcGIS Services Directory. See the Discovering Services topic for more information. This example uses the states layer of the ESRI_Census_USA service.
  10. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    	graphicsLayer.Graphics.Add(graphic);
    
    	IdentifyTask identifyTask = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
    		"Demographics/ESRI_Census_USA/MapServer");
    }

  11. Specify a handler for the task's ExecuteCompleted event. The method specified will be called when the Identify task is done executing. You will implement this handler in the "Displaying results" section.
  12. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    	graphicsLayer.Graphics.Add(graphic);
    
    	IdentifyTask identifyTask = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
    		"Demographics/ESRI_Census_USA/MapServer");
    	identifyTask.ExecuteCompleted += IdentifyTask_ExecuteCompleted;
    }

  13. Specify a handler for the task's Failed event, which fires when there is a problem executing the task. You will define this handler in the "Handling execution errors" section.
  14. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    	graphicsLayer.Graphics.Add(graphic);
    
    	IdentifyTask identifyTask = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
    		"Demographics/ESRI_Census_USA/MapServer");
    	identifyTask.ExecuteCompleted += IdentifyTask_ExecuteCompleted;
    	identifyTask.Failed += IdentifyTask_Failed;
    }

  15. Instantiate a new IdentifyParameters object. The IdentifyParameters object is used to specify the input for Identify tasks.
  16. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    	graphicsLayer.Graphics.Add(graphic);
    
    	IdentifyTask identifyTask = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
    		"Demographics/ESRI_Census_USA/MapServer");
    	identifyTask.ExecuteCompleted += IdentifyTask_ExecuteCompleted;
    	identifyTask.Failed += IdentifyTask_Failed;
    
    	IdentifyParameters identifyParameters = new IdentifyParameters();
    }

  17. Specify that all the map service's layers be searched. The LayerOption parameter can also be set to search only the top-most or visible layers.
  18. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    	graphicsLayer.Graphics.Add(graphic);
    
    	IdentifyTask identifyTask = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
    		"Demographics/ESRI_Census_USA/MapServer");
    	identifyTask.ExecuteCompleted += IdentifyTask_ExecuteCompleted;
    	identifyTask.Failed += IdentifyTask_Failed;
    
    	IdentifyParameters identifyParameters = new IdentifyParameters();
    	identifyParameters.LayerOption = LayerOption.all;
    }

  19. Use the Map control's properties to initialize the map extent, width, and height of the Identify parameters.
  20. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    	graphicsLayer.Graphics.Add(graphic);
    
    	IdentifyTask identifyTask = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
    		"Demographics/ESRI_Census_USA/MapServer");
    	identifyTask.ExecuteCompleted += IdentifyTask_ExecuteCompleted;
    	identifyTask.Failed += IdentifyTask_Failed;
    
    	IdentifyParameters identifyParameters = new IdentifyParameters();
    	identifyParameters.LayerOption = LayerOption.all;
    
    	identifyParameters.MapExtent = MyMap.Extent;
    	identifyParameters.Width = (int)MyMap.ActualWidth;
    	identifyParameters.Height = (int)MyMap.ActualHeight;
    }

  21. Set the search geometry for the Identify task to be the point clicked on the map.
  22. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    	graphicsLayer.Graphics.Add(graphic);
    
    	IdentifyTask identifyTask = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
    		"Demographics/ESRI_Census_USA/MapServer");
    	identifyTask.ExecuteCompleted += IdentifyTask_ExecuteCompleted;
    	identifyTask.Failed += IdentifyTask_Failed;
    
    	IdentifyParameters identifyParameters = new IdentifyParameters();
    	identifyParameters.LayerOption = LayerOption.all;
    
    	identifyParameters.MapExtent = MyMap.Extent;
    	identifyParameters.Width = (int)MyMap.ActualWidth;
    	identifyParameters.Height = (int)MyMap.ActualHeight;
    
    	identifyParameters.Geometry = args.MapPoint;
    }

  23. Execute the Identify task.
  24. private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs args)
    {
    	GraphicsLayer graphicsLayer = MyMap.Layers["IdentifyIconGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.ClearGraphics();
    	ESRI.ArcGIS.Client.Graphic graphic = new ESRI.ArcGIS.Client.Graphic()
    	{
    		Geometry = args.MapPoint,
    		Symbol = IdentifyLocationSymbol
    	};
    	graphicsLayer.Graphics.Add(graphic);
    
    	IdentifyTask identifyTask = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
    		"Demographics/ESRI_Census_USA/MapServer");
    	identifyTask.ExecuteCompleted += IdentifyTask_ExecuteCompleted;
    	identifyTask.Failed += IdentifyTask_Failed;
    
    	IdentifyParameters identifyParameters = new IdentifyParameters();
    	identifyParameters.LayerOption = LayerOption.all;
    
    	identifyParameters.MapExtent = MyMap.Extent;
    	identifyParameters.Width = (int)MyMap.ActualWidth;
    	identifyParameters.Height = (int)MyMap.ActualHeight;
    
    	identifyParameters.Geometry = args.MapPoint;
    
    	identifyTask.ExecuteAsync(identifyParameters);
    }

Displaying results

In the handler for the Map's MouseClick event, you specified IdentifyTask_ExecuteCompleted as the handler for the task's ExecuteCompleted event. This event receives the Identify task's results, which consist of information about all the features in the specified search layers (all, visible, or top-most) that intersect the search geometry. In the main page's XAML, recall that you also declared a ComboBox to hold the results features, a DataGrid to display the selected feature's attributes, and a GraphicsLayer to show the selected feature's geometry. On the ComboBox, you specified the IdentifyComboBox_SelectionChanged method as the handler for the ComboBox's SelectionChanged event.

In this section, you will implement the ExecuteCompleted handler to populate the Identify ComboBox with a list of the features' display values. Then you will implement the SelectionChanged handler to display the attributes of the ComboBox's selected feature in the DataGrid and the geometry of that feature on the GraphicsLayer.

  1. Declare a handler for the Identify task's ExecuteCompleted event. This handler will be invoked when an identify operation is complete. A list of IdentifyResults containing information about the features with geometries intersecting the search geometry is passed to the handler's args parameter. Each IdentifyResult contains the feature found, the name and ID of the layer containing the feature, the value of the feature's display field, and other information.
  2. private void IdentifyTask_ExecuteCompleted(object sender, IdentifyEventArgs args)
    {
    }

  3. Remove previous results from the Identify ComboBox and check whether any results were found for the current operation.
  4. private void IdentifyTask_ExecuteCompleted(object sender, IdentifyEventArgs args)
    {
        IdentifyComboBox.Items.Clear();
    
        if (args.IdentifyResults.Count > 0)
        {
        }
        else
        {
        }
    }

  5. If results were found, make the StackPanel containing the Identify ComboBox and results DataGrid visible.
  6. private void IdentifyTask_ExecuteCompleted(object sender, IdentifyEventArgs args)
    {
        IdentifyComboBox.Items.Clear();
    
        if (args.IdentifyResults.Count > 0)
        {
            IdentifyResultsStackPanel.Visibility = Visibility.Visible;
        }
        else
        {
        }
    }

  7. Loop through the result features. For each one, add its display value and layer to the Identify ComboBox. Then call the ComboBox's UpdateLayout method to apply the updates.
  8. private void IdentifyTask_ExecuteCompleted(object sender, IdentifyEventArgs args)
    {
        IdentifyComboBox.Items.Clear();
    
        if (args.IdentifyResults.Count > 0)
        {
            IdentifyResultsStackPanel.Visibility = Visibility.Visible;
    
            foreach (IdentifyResult result in args.IdentifyResults)
            {
                string title = string.Format("{0} ({1})", result.Value.ToString(), result.LayerName);
                IdentifyComboBox.Items.Add(title);
            }
    
            IdentifyComboBox.UpdateLayout();
        }
        else
        {
        }
    }

  9. At the top of the main page's class, declare an IdentifyResults member variable. This will be used to store the most recently returned set of task results for use when a new result is selected from the ComboBox
  10. public partial class Page : UserControl
    {
    	private List<IdentifyResult> _lastIdentifyResult;
    	.
    	.
    	.
    }

  11. Store the Identify task's results in the member variable.
  12. private void IdentifyTask_ExecuteCompleted(object sender, IdentifyEventArgs args)
    {
        IdentifyComboBox.Items.Clear();
    
        if (args.IdentifyResults.Count > 0)
        {
            IdentifyResultsStackPanel.Visibility = Visibility.Visible;
    
            foreach (IdentifyResult result in args.IdentifyResults)
            {
                string title = string.Format("{0} ({1})", result.Value.ToString(), result.LayerName);
                IdentifyComboBox.Items.Add(title);
            }
    
            IdentifyComboBox.UpdateLayout();
    
    		_lastIdentifyResult = args.IdentifyResults;
        }
        else
        {
        }
    }

  13. Initialize the SelectedIndex of the Identify ComboBox so that the first item in the list is displayed. This will also fire the ComboBox's SelectionChanged event, which you will implement to update the Identify results DataGrid and draw the selected feature on the Map.
  14. private void IdentifyTask_ExecuteCompleted(object sender, IdentifyEventArgs args)
    {
        IdentifyComboBox.Items.Clear();
    
        if (args.IdentifyResults.Count > 0)
        {
            IdentifyResultsStackPanel.Visibility = Visibility.Visible;
    
            foreach (IdentifyResult result in args.IdentifyResults)
            {
                string title = string.Format("{0} ({1})", result.Value.ToString(), result.LayerName);
                IdentifyComboBox.Items.Add(title);
            }
    
            IdentifyComboBox.UpdateLayout();
    
    		_lastIdentifyResult = args.IdentifyResults;
    
            IdentifyComboBox.SelectedIndex = 0;
        }
        else
        {
        }
    }

  15. If no features were found, hide the StackPanel containing the Identify ComboBox and DataGrid. Notify the user with a MessageBox.
  16. private void IdentifyTask_ExecuteCompleted(object sender, IdentifyEventArgs args)
    {
        IdentifyComboBox.Items.Clear();
    
        if (args.IdentifyResults.Count > 0)
        {
            IdentifyResultsStackPanel.Visibility = Visibility.Visible;
    
            foreach (IdentifyResult result in args.IdentifyResults)
            {
                string title = string.Format("{0} ({1})", result.Value.ToString(), result.LayerName);
                IdentifyComboBox.Items.Add(title);
            }
    
            IdentifyComboBox.UpdateLayout();
    
    		_lastIdentifyResult = args.IdentifyResults;
    
            IdentifyComboBox.SelectedIndex = 0;
        }
        else
        {
            IdentifyResultsStackPanel.Visibility = Visibility.Collapsed;
            MessageBox.Show("No features found");
        }
    }

  17. Declare the IdentifyComboBox_SelectionChanged method. In the page's XAML, you specified this method as the handler for the IdentifyComboBox's SelectionChanged event. The SelectionChanged event fires whenever the selected item in the ComboBox is changed. Note this includes both interactive and programmatic changes to the selected item, even when the selecton is not valid (e.g. the ComboBox is cleared).

    void IdentifyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    }

  18. Retrieve the GraphicsLayer for displaying the currently selected feature and clear it of any previously displayed results.
  19. void IdentifyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        GraphicsLayer graphicsLayer = MyMap.Layers["ResultsGraphicsLayer"] as GraphicsLayer;
        graphicsLayer.ClearGraphics();
    }

  20. Check whether an item is currently selected. If no item is selected, the ComboBox's SelectedIndex will be -1.
  21. void IdentifyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        GraphicsLayer graphicsLayer = MyMap.Layers["ResultsGraphicsLayer"] as GraphicsLayer;
        graphicsLayer.ClearGraphics();
    
        if (IdentifyComboBox.SelectedIndex > -1)
        {
        }
    }

  22. If an item is selected, get the Graphic (i.e. feature) corresponding to that item. For this, the LastResult property on the Identify task is useful. This property holds the set of results returned by the most recently executed Identify operation.
  23. void IdentifyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        GraphicsLayer graphicsLayer = MyMap.Layers["ResultsGraphicsLayer"] as GraphicsLayer;
        graphicsLayer.ClearGraphics();
    
        if (IdentifyComboBox.SelectedIndex > -1)
        {
            Graphic selectedFeature = _lastIdentifyResult[IdentifyComboBox.SelectedIndex].Feature;
        }
    }

  24. Update the Identify DataGrid to show the attributes of the selected feature. In the page's XAML, recall that you specified two columns in the DataGrid and that they be bound to properties called Key and Value. A Graphic object keeps its attribute in a Dictionary, which is simply a list of key/value pairs - each item defines Key and Value properties. You can thus bind the DataGrid to the selected Graphic (i.e. feature) by passing this attributes Dictionary to the DataGrid's ItemsSource property.
  25. void IdentifyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        GraphicsLayer graphicsLayer = MyMap.Layers["ResultsGraphicsLayer"] as GraphicsLayer;
        graphicsLayer.ClearGraphics();
    
        if (IdentifyComboBox.SelectedIndex > -1)
        {
            Graphic selectedFeature = _lastIdentifyResult[IdentifyComboBox.SelectedIndex].Feature;
            IdentifyDetailsDataGrid.ItemsSource = selectedFeature.Attributes;
        }
    }

  26. Apply the fill symbol you defined in the page's XAML to the selected feature and add the feature to the results GraphicsLayer.
  27. void IdentifyComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        GraphicsLayer graphicsLayer = MyMap.Layers["ResultsGraphicsLayer"] as GraphicsLayer;
        graphicsLayer.ClearGraphics();
    
        if (IdentifyComboBox.SelectedIndex > -1)
        {
            Graphic selectedFeature = _lastIdentifyResult[IdentifyComboBox.SelectedIndex].Feature;
            IdentifyDetailsDataGrid.ItemsSource = selectedFeature.Attributes;
    
            selectedFeature.Symbol = SelectedFeatureSymbol;
            graphicsLayer.Graphics.Add(selectedFeature);
        }
    }

Handling execution errors

  1. Declare a handler for the Identify task's Failed event. This handler will be invoked if there is a problem with executing an identify operation.
  2. private void IdentifyTask_Failed(object sender, TaskFailedEventArgs args)
    {
    }

  3. Notify the user of the problem with a MessageBox
  4. private void IdentifyTask_Failed(object sender, TaskFailedEventArgs args)
    {
        MessageBox.Show("Identify failed: " + args.Error);
    }