How to create a Locator task

The Locator task allows you to perform geocoding and reverse geocoding operations. With the Locator, you can either find the geographic location of an address or the address of a geographic location.

The code for a sample WPF application that uses the Locator task to enable both geocoding and reverse geocoding is shown below. To enable geocoding, the code defines TextBoxes for inputting address information and a Button to initiate the operation. Reverse geocoding is triggered by clicking the Map. Both geocoding and reverse geocoding results are drawn in GraphicLayers that have MapTips enabled. The remainder of this topic will walk you through the sample, paying particular attention to how the task is used, including a section on how to use the locator with online data.

<Window x:Class="ArcGISWpfApplication1.MainWindow"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:esri="http://schemas.esri.com/arcgis/client/2009"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="LayoutRoot">
        <Grid.Resources>
            <esri:SimpleMarkerSymbol x:Key="GeocodingSymbol" Color="Red"/>
            <esri:SimpleMarkerSymbol x:Key="ReverseGeocodingSymbol" Color="Blue"/>
        </Grid.Resources>

        <esri:Map x:Name="MyMap" Extent="-122.519985221, 37.836494682 ,-122.302264539 , 37.698485944" MouseClick="MyMap_MouseClick">
            <esri:Map.Layers>
               <esri:ArcGISLocalTiledLayer ID="San Francisco" Path="C:\Program Files (x86)\ArcGIS SDKs\WPF10.2.5\sdk\samples\data\tpks\SanFrancisco.tpk"/>
                <esri:GraphicsLayer ID="GeocodingGraphicsLayer">
                    <esri:GraphicsLayer.MapTip>
                        <Grid Background="LightYellow">
                            <StackPanel Orientation="Vertical" Margin="5" >
                                <TextBlock Text="{Binding [Address]}" HorizontalAlignment="Left" Foreground="Black" />
                                <TextBlock Text="{Binding [LatLon]}" HorizontalAlignment="Left" Foreground="Black" />
                            </StackPanel>
                            <Border BorderBrush="Black" BorderThickness="1" />
                        </Grid>
                    </esri:GraphicsLayer.MapTip>
                </esri:GraphicsLayer>
                <esri:GraphicsLayer ID="ReverseGeocodingGraphicsLayer">
                    <esri:GraphicsLayer.MapTip>
                        <Grid Background="LightYellow">
                            <StackPanel Orientation="Vertical" Margin="5" >
                                <TextBlock Text="{Binding [Address1]}" HorizontalAlignment="Left" Foreground="Black" />
                                <TextBlock Text="{Binding [LatLon]}" HorizontalAlignment="Left" Foreground="Black" />
                            </StackPanel>
                            <Border BorderBrush="Black" BorderThickness="1" />
                        </Grid>
                    </esri:GraphicsLayer.MapTip>
                </esri:GraphicsLayer>
            </esri:Map.Layers>
        </esri:Map>

        <StackPanel Margin="10" HorizontalAlignment="Left">
            <Grid>
                <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
                <StackPanel Margin="10" HorizontalAlignment="Center" >
                    <TextBlock Text="Click Find to locate an address" HorizontalAlignment="Center" 
						   Margin="0,0,0,5" Foreground="White" FontStyle="Italic" />
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                        <TextBlock Text="Street: " Foreground="White" />
                        <TextBox x:Name="Street" Text="2011 MISSION ST" Width="125" />
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                        <TextBlock Text="City: " Foreground="White" />
                        <TextBox x:Name="City" Text="SAN FRANCISCO " Width="125" />
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                        <TextBlock Text="State: " Foreground="White" />
                        <TextBox x:Name="State" Text="CA " Width="125"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                        <TextBlock Text="ZIP: " Foreground="White" />
                        <TextBox x:Name="ZIP" Text="94103" Width="125" />
                    </StackPanel>
                    <Button x:Name="FindAddressButton" Content="Find" Width="100" HorizontalAlignment="Center"
					Click="FindAddressButton_Click" Margin="0,5,0,0" />
                    <Line HorizontalAlignment="Center" X1="0" Y1="10" X2="180" Y2="10" StrokeThickness="1" Stroke="White" />
                    <TextBlock Text="Or click map to retrieve address" FontStyle="Italic" HorizontalAlignment="Center" 
				   Foreground="White" Margin="0,10,0,0" />
                </StackPanel>
            </Grid>
        </StackPanel>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Tasks;
using ESRI.ArcGIS.Client.Local;

namespace ArcGISWpfApplication1
{

    public partial class MainWindow : Window
    {
        Locator locatorTask;

        public MainWindow()
        {
            InitializeComponent();

            LocalGeocodeService.GetServiceAsync(@"C:\Program Files (x86)\ArcGIS SDKs\WPF10.2.5\sdk\samples\data\locators\SanFrancisco\SanFranciscoLocator.gcpk", 
            "SanFranciscoLocator", gs =>
            {
                locatorTask = new Locator(gs.UrlGeocodeService);
                locatorTask.LocationToAddressCompleted += LocatorTask_LocationToAddressCompleted;
                locatorTask.AddressToLocationsCompleted += LocatorTask_AddressToLocationsCompleted;
                locatorTask.Failed += LocatorTask_Failed;
            });
        }

        private void MyMap_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
        {
                locatorTask.LocationToAddressAsync(e.MapPoint, 50);
        }

        private void FindAddressButton_Click(object sender, RoutedEventArgs e)
        {
            AddressToLocationsParameters addressParameters = new AddressToLocationsParameters();
            Dictionary<string, string> address = addressParameters.Address;
            address.Add("Street", Street.Text);
            address.Add("City", City.Text);
            address.Add("State", State.Text);
            address.Add("ZIP", ZIP.Text);
            locatorTask.AddressToLocationsAsync(addressParameters);
        }

        private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
        {
            if (args.Results.Count > 0)
            {
                AddressCandidate bestCandidate = args.Results[0];
                foreach (AddressCandidate candidate in args.Results)
                    bestCandidate = (candidate.Score > bestCandidate.Score) ? candidate : bestCandidate;
                Graphic graphic = new Graphic()
                {
                    Geometry = bestCandidate.Location,
                    Symbol = LayoutRoot.Resources["GeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol
                };

                graphic.Attributes.Add("Address", bestCandidate.Address);
                string latLon = String.Format("{0}, {1}", bestCandidate.Location.X, bestCandidate.Location.Y);
                graphic.Attributes.Add("LatLon", latLon);
                GraphicsLayer graphicsLayer = MyMap.Layers["GeocodingGraphicsLayer"] as GraphicsLayer;
                graphicsLayer.Graphics.Clear();
                graphicsLayer.Graphics.Add(graphic);
            }
            else
            {

                MessageBox.Show("No results found");
            }

        }

        private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args)
        {
            Address address = args.Address;
            Dictionary<string, object> attributes = args.Address.Attributes;
            Graphic graphic = new Graphic()
            {
                Symbol = LayoutRoot.Resources["ReverseGeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
                Geometry = address.Location,
            };

            string latLon = String.Format("{0}, {1}", address.Location.X, address.Location.Y);
            string address1 = String.Format("{0}, {1} {2}", attributes["Street"], attributes["State"], attributes["ZIP"]);
            graphic.Attributes.Add("LatLon", latLon);
            graphic.Attributes.Add("Address1", address1);
            GraphicsLayer graphicsLayer = MyMap.Layers["ReverseGeocodingGraphicsLayer"] as GraphicsLayer;
            graphicsLayer.Graphics.Add(graphic);
        }
        private void LocatorTask_Failed(object sender, TaskFailedEventArgs e)
        {
            MessageBox.Show("Locator service failed: " + e.Error);
        }

    }

}

Using a Locator task

The following steps assume you have created a WPF application with a local map. The XAML view of your application's main window (e.g. MainWindow.xaml) should look similar to the following:

<Window x:Class="ArcGISWpfApplication1.MainWindow"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:esri="http://schemas.esri.com/arcgis/client/2009"
        Title="MainWindow" Height="350" Width="525">
    <Grid x:Name="LayoutRoot">      
        <esri:Map x:Name="MyMap" Extent="-122.519985221, 37.836494682 ,-122.302264539 , 37.698485944"> 
          <esri:Map.Layers>
            <esri:ArcGISLocalTiledLayer ID="San Francisco" Path="C:\Program Files (x86)\ArcGIS SDKs\WPF10.2.5\sdk\samples\data\tpks\SanFrancisco.tpk"/> 
         </esri:Map.Layers>
       </esri:Map>
    </Grid>
</Window>

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

Create the input interface

Tasks do not define user interfaces, so it's up to you as a developer to implement an interface for the Locator's input. For geocoding input, you will define a TextBlock for instructions, TextBoxes for the address information, and a Button to start the operation. For reverse geocoding, you will specify a TextBlock for instructions and a handler for the Map's MouseClick event.

  1. In XAML, define the background for the task's input interface. In the structure shown below, the Rectangle will define the background color and will automatically fit to elements within the inner StackPanel.
    <StackPanel Margin="10" HorizontalAlignment="Left">
    	<Grid>
    		<Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
    		<StackPanel Margin="10" HorizontalAlignment="Center" >
    		</StackPanel>
    	</Grid>
    </StackPanel>
    
  2. Specify the geocoding interface. Use a TextBlock for the operation instructions, TextBoxes for the address information, and a Button to initiate the operation. Be sure to specify a handler for the Button's click event. Later in the walkthrough, you will implement this handler so that it processes the user input and starts the geocoding operation.
    <StackPanel Margin="10" HorizontalAlignment="Left">
                <Grid>
                    <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
                    <StackPanel Margin="10" HorizontalAlignment="Center" >
                        <TextBlock Text="Click Find to locate an address" HorizontalAlignment="Center" 
    						   Margin="0,0,0,5" Foreground="White" FontStyle="Italic" />
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                            <TextBlock Text="Street: " Foreground="White" />
                            <TextBox x:Name="Street" Text="2011 MISSION ST" Width="125" />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                            <TextBlock Text="City: " Foreground="White" />
                            <TextBox x:Name="City" Text="SAN FRANCISCO " Width="125" />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                            <TextBlock Text="State: " Foreground="White" />
                            <TextBox x:Name="State" Text="CA " Width="125"/>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                            <TextBlock Text="ZIP: " Foreground="White" />
                            <TextBox x:Name="ZIP" Text="94103" Width="125" />
                        </StackPanel>
                        <Button x:Name="FindAddressButton" Content="Find" Width="100" HorizontalAlignment="Center"
    					Click="FindAddressButton_Click" Margin="0,5,0,0" />                   
                    </StackPanel>
                </Grid>
            </StackPanel>
    
  3. Specify instructions for reverse geocoding. Add a separator line below the geocoding interface and a TextBlock containing the instructions.
    <StackPanel Margin="10" HorizontalAlignment="Left">
                <Grid>
                    <Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
                    <StackPanel Margin="10" HorizontalAlignment="Center" >
                        <TextBlock Text="Click Find to locate an address" HorizontalAlignment="Center" 
    						   Margin="0,0,0,5" Foreground="White" FontStyle="Italic" />
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                            <TextBlock Text="Street: " Foreground="White" />
                            <TextBox x:Name="Street" Text="2011 MISSION ST" Width="125" />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                            <TextBlock Text="City: " Foreground="White" />
                            <TextBox x:Name="City" Text="SAN FRANCISCO " Width="125" />
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                            <TextBlock Text="State: " Foreground="White" />
                            <TextBox x:Name="State" Text="CA " Width="125"/>
                        </StackPanel>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
                            <TextBlock Text="ZIP: " Foreground="White" />
                            <TextBox x:Name="ZIP" Text="94103" Width="125" />
                        </StackPanel>
                        <Button x:Name="FindAddressButton" Content="Find" Width="100" HorizontalAlignment="Center"
    					Click="FindAddressButton_Click" Margin="0,5,0,0" />                   
                    </StackPanel>
                </Grid>
            </StackPanel>
    
  4. On the Map control, specify a handler for the MouseClick event. You will implement this handler later so that it uses the click point to initiate a reverse geocoding operation.
    <esri:Map x:Name="MyMap" Extent="-122.519985221, 37.836494682 ,-122.302264539 , 37.698485944"
     MouseClick="MyMap_MouseClick">
                <esri:Map.Layers>
                    <esri:ArcGISLocalTiledLayer ID="San Francisco" Path="C:\Program Files (x86)\ArcGIS SDKs\WPF10.2.5\sdk\samples\data\tpks\SanFrancisco.tpk"/>
                  </esri:Map.Layers>
            </esri:Map>
    

Creating the output interface

To display a task's results, you need to specify an output interface. For displaying the geometry of result features, you will use two GraphicsLayers and two SimpleMarkerSymbols—one layer/symbol pair for geocoding output and one for reverse geocoding output. Then you will specify MapTips on each GraphicsLayer for displaying non-geographic results data. The MapTips will bind to attributes on the task's results.

  1. Now declare two SimpleMarkerSymbols as resources of the root Grid element
    <Grid x:Name="LayoutRoot">
            <Grid.Resources>
                <esri:SimpleMarkerSymbol x:Key="GeocodingSymbol" Color="Red"/>
                <esri:SimpleMarkerSymbol x:Key="ReverseGeocodingSymbol" Color="Blue"/>
            </Grid.Resources>
    
  2. Add two GraphicsLayers to the Map control XAML element—one each for geocoding and reverse geocoding results. Note that the GraphicsLayers are specified below the map service layer in the XAML so that they are drawn above the map service layer at run time.
    <esri:Map x:Name="MyMap" Extent="-122.519985221, 37.836494682 ,-122.302264539 , 37.698485944"
             MouseClick="MyMap_MouseClick">
                <esri:Map.Layers>
                    <esri:ArcGISLocalTiledLayer ID="San Francisco" Path="C:\Program Files (x86)\ArcGIS SDKs\WPF10.2.5\sdk\samples\data\tpks\SanFrancisco.tpk"/>
                    <esri:GraphicsLayer ID="GeocodingGraphicsLayer">               
                    </esri:GraphicsLayer>
                    <esri:GraphicsLayer ID="ReverseGeocodingGraphicsLayer">               
                    </esri:GraphicsLayer>
                </esri:Map.Layers>
            </esri:Map>
    
  3. Within the element for the geocoding (i.e. address to location) results GraphicsLayer, specify a MapTip to display the non-geographic data of the results. Bind the MapTip to attributes called Address and LatLon. You will explicitly add these attributes to the geocoding results in the window's code-behind.
    <esri:Map x:Name="MyMap" Extent="-122.519985221, 37.836494682 ,-122.302264539 , 37.698485944" 
    MouseClick="MyMap_MouseClick">
     <esri:Map.Layers>
     <esri:ArcGISLocalTiledLayer ID="San Francisco" Path="C:\Program Files (x86)\ArcGIS SDKs\WPF10.2.5\sdk\samples\data\tpks\SanFrancisco.tpk"/>
          <esri:GraphicsLayer ID="GeocodingGraphicsLayer">
               <esri:GraphicsLayer.MapTip>
                  <Grid Background="LightYellow">
                 <StackPanel Orientation="Vertical" Margin="5" >
                  <TextBlock Text="{Binding [Address]}" HorizontalAlignment="Left" Foreground="Black" />
                   <TextBlock Text="{Binding [LatLon]}" HorizontalAlignment="Left" Foreground="Black" />
                 </StackPanel>
               <Border BorderBrush="Black" BorderThickness="1" />
             </Grid>
           </esri:GraphicsLayer.MapTip>
         </esri:GraphicsLayer>
       <esri:GraphicsLayer ID="ReverseGeocodingGraphicsLayer">                   
      </esri:GraphicsLayer>
    </esri:Map.Layers>
      </esri:Map>
    
  4. On the reverse geocoding (i.e. location to address) results GraphicsLayer, specify a MapTip that will bind to attributes called Address1 and LatLon.
    <esri:Map x:Name="MyMap" Extent="-122.519985221, 37.836494682 ,-122.302264539 , 37.698485944" MouseClick="MyMap_MouseClick">
                <esri:Map.Layers>
                    <esri:ArcGISLocalTiledLayer ID="San Francisco" Path="C:\Program Files (x86)\WPF10.2.5\sdk\samples\data\tpks\SanFrancisco.tpk"/>
                    <esri:GraphicsLayer ID="GeocodingGraphicsLayer">
                        <esri:GraphicsLayer.MapTip>
                            <Grid Background="LightYellow">
                                <StackPanel Orientation="Vertical" Margin="5" >
                                    <TextBlock Text="{Binding [Address]}" HorizontalAlignment="Left" Foreground="Black" />
                                    <TextBlock Text="{Binding [LatLon]}" HorizontalAlignment="Left" Foreground="Black" />
                                </StackPanel>
                                <Border BorderBrush="Black" BorderThickness="1" />
                            </Grid>
                        </esri:GraphicsLayer.MapTip>
                    </esri:GraphicsLayer>
                    <esri:GraphicsLayer ID="ReverseGeocodingGraphicsLayer">
                        <esri:GraphicsLayer.MapTip>
                            <Grid Background="LightYellow">
                                <StackPanel Orientation="Vertical" Margin="5" >
                                    <TextBlock Text="{Binding [Address1]}" HorizontalAlignment="Left" Foreground="Black" />
                                    <TextBlock Text="{Binding [LatLon]}" HorizontalAlignment="Left" Foreground="Black" />
                                </StackPanel>
                                <Border BorderBrush="Black" BorderThickness="1" />
                            </Grid>
                        </esri:GraphicsLayer.MapTip>
                    </esri:GraphicsLayer>
                </esri:Map.Layers>
            </esri:Map>
    

Implement the task's execution logic

Now that you've specified the Locator task's user interface, you need to define its execution logic. As previously mentioned, this task can perform both geocoding and reverse geocoding. In this section, you will implement the Find button's click event handler to initiate a geocoding operation by calling the task's AddressToLocationsAsync method. Then you will define a handler for the Map's MouseClick event to perform reverse geocoding by calling the task's LocationToAddressAsync method. The code for these handlers will be implemented in .NET code contained in the main window's code-behind.

To use the Locator's execution methods, you need to instantiate the task, specify the geocoding service that will be used to lookup address information, wire the task's event handlers, initialize the operation's parameters, and call the execution method. The steps below will show you how to do this in the code-behind of your application's main window (e.g. MainWindow.xaml.cs). 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.

The code shown in these steps is written in C#.

Initiate a geocoding operation

  1. Find the default constructor and asynchronously start the LocalGeocodeService. When the callback is raised instantiate the LocatorTask. The Locator constructor accepts the LocalGeocodeService URL. Specify a handler for the task's AddressToLocationsCompleted event. The method specified will be called when the Address Locator task is has completed a geocode operation. You will implement this handler in the "Handle geocoding results" section. Also specify a handler for the task's Failed event, which fires when there is a problem performing a geocoding or reverse geocoding operation. You will define this handler in the "Handling execution errors" section. Finally, specify a handler for the task's LocationToAddressCompleted event. The method specified will be called when the Locator task is has completed a reverse geocode operation. You will implement this handler in the "Handle reverse geocoding results" section.
    LocalGeocodeService.GetServiceAsync(@"C:\Program Files (x86)\ArcGIS SDKs\WPF10.2.5\sdk\samples\data\locators\SanFrancisco\SanFranciscoLocator.gcpk", 
                "SanFranciscoLocator", gs =>
                {
                    locatorTask = new Locator(gs.UrlGeocodeService);
                    locatorTask.LocationToAddressCompleted += LocatorTask_LocationToAddressCompleted;
                    locatorTask.AddressToLocationsCompleted += LocatorTask_AddressToLocationsCompleted;
                    locatorTask.Failed += LocatorTask_Failed;
                });
    
  2. In the code-behind class of your application's main window, implement a handler for the FindAddressButton's click event. Recall that you declared this handler when you defined the FindAddressButton control in the window's XAML.
    private void FindAddressButton_Click(object sender, RoutedEventArgs e)
    {
    
    }
    
  3. Declare and instantiate an AddressToLocationsParameters object. This object is used to define the execution parameters for geocoding operations.
    private void FindAddressButton_Click(object sender, RoutedEventArgs e)
    {
    		
    	AddressToLocationsParameters addressParameters = new AddressToLocationsParameters();
    
    }
    
  4. Retrieve the address information from the input TextBoxes you specified in the window's XAML and use it to initialize the parameter object's Address property.
    private void FindAddressButton_Click(object sender, RoutedEventArgs e)
    {
    	
    AddressToLocationsParameters addressParameters = new AddressToLocationsParameters();
    Dictionary<string, string> address = addressParameters.Address;
    address.Add("Street", Street.Text);
    address.Add("City", City.Text);
    address.Add("State", State.Text);
    address.Add("ZIP", ZIP.Text);
    
    }
    
  5. Execute the geocoding operation with the specified address.
    private void FindAddressButton_Click(object sender, RoutedEventArgs e)
    {
    	
    AddressToLocationsParameters addressParameters = new AddressToLocationsParameters();
    Dictionary<string, string> address = addressParameters.Address;
    address.Add("Street", Street.Text);
    address.Add("City", City.Text);
    address.Add("State", State.Text);
    address.Add("ZIP", ZIP.Text);
    	locatorTask.AddressToLocationsAsync(addressParameters);
    
    }
    

Initiate a reverse geocoding operation

  1. In the code-behind class of your application's main window, implement a handler for the Map's MouseClick event. Recall that you declared this handler when you specified the name of this handler on the Map element in the window's XAML.
    private void MyMap_MouseClick(object sender, Map.MouseEventArgs e)
    {
    }
    
  2. Execute the reverse geocoding operation to find the address at the point clicked on the map. Specify a tolerance of 50 for the operation. This means that the task will search within 50 meters of the click point to find the nearest address.
    private void MyMap_MouseClick(object sender, Map.MouseEventArgs e)
    {
    	locatorTask.LocationToAddressAsync(e.MapPoint, 50);
    }
    

Handle geocoding results

  1. Declare a handler for the Address Locator task's AddressToLocationsCompleted event. This handler will be invoked when a geocoding operation is complete. A list of AddressCandidates containing information about the possible matches for the input address is passed to the handler's args parameter. Each AddressCandidate contains the score, address, and location for the match.
    private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
    {
    }
    
  2. Check whether any results were found.
    private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
    {
    	if (args.Results.Count > 0)
    	{
    	}
    	else
    	{
    	}
    }
    
  3. If results were found, loop through them and store a reference to the one with the highest match score.
    private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
    {
    	if (args.Results.Count > 0)
    	{
    		AddressCandidate bestCandidate = args.Results[0];
    		foreach (AddressCandidate candidate in args.Results)
    			bestCandidate = (candidate.Score > bestCandidate.Score) ? candidate : bestCandidate;
    	}
    	else
    	{
    	}
    }
    
  4. Create a Graphic to display the best match on the Map. Initialize it with the result's location and the geocoding result symbol you defined in the window's XAML.
    private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
    {
    	if (args.Results.Count > 0)
    	{
    		AddressCandidate bestCandidate = args.Results[0];
    		foreach (AddressCandidate candidate in args.Results)
    			bestCandidate = (candidate.Score > bestCandidate.Score) ? candidate : bestCandidate;
    
    		Graphic graphic = new Graphic()
    		{
    			Symbol = LayoutRoot.Resources["GeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    			Geometry = bestCandidate.Location
    		};
    	}
    	else
    	{
    	}
    }
    
  5. Add the Address of the result to the graphic. Specify an attribute name of Address, which will allow the value to be bound to a MapTip through XAML you specified earlier.
    private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
    {
    	if (args.Results.Count > 0)
    	{
    		AddressCandidate bestCandidate = args.Results[0];
    		foreach (AddressCandidate candidate in args.Results)
    			bestCandidate = (candidate.Score > bestCandidate.Score) ? candidate : bestCandidate;
    
    		Graphic graphic = new Graphic()
    		{
    			Symbol = LayoutRoot.Resources["GeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    			Geometry = bestCandidate.Location
    		};
    
    		graphic.Attributes.Add("Address", bestCandidate.Address);
    	}
    	else
    	{
    		MessageBox.Show("No results found");
    	}
    }
    
  6. Add the coordinates of the result to the Graphic in an attribute named LatLon. This attribute will also be bound to the Graphic's MapTip through XAML you specified earlier.
    private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
    {
    	if (args.Results.Count > 0)
    	{
    		AddressCandidate bestCandidate = args.Results[0];
    		foreach (AddressCandidate candidate in args.Results)
    			bestCandidate = (candidate.Score > bestCandidate.Score) ? candidate : bestCandidate;
    
    		Graphic graphic = new Graphic()
    		{
    			Symbol = LayoutRoot.Resources["GeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    			Geometry = bestCandidate.Location
    		};
    
    		graphic.Attributes.Add("Address", bestCandidate.Address);
    		string latLon = String.Format("{0}, {1}", bestCandidate.Location.X, bestCandidate.Location.Y);
    		graphic.Attributes.Add("LatLon", latLon);
    	}
    	else
    	{
    	}
    }
    
  7. Retrieve the geocoding results GraphicsLayer and clear it of any previous results.
    private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
    {
    	if (args.Results.Count > 0)
    	{
    		AddressCandidate bestCandidate = args.Results[0];
    		foreach (AddressCandidate candidate in args.Results)
    			bestCandidate = (candidate.Score > bestCandidate.Score) ? candidate : bestCandidate;
    
    		Graphic graphic = new Graphic()
    		{
    			Symbol = LayoutRoot.Resources["GeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    			Geometry = bestCandidate.Location
    		};
    
    		graphic.Attributes.Add("Address", bestCandidate.Address);
    		string latLon = String.Format("{0}, {1}", bestCandidate.Location.X, bestCandidate.Location.Y);
    		graphic.Attributes.Add("LatLon", latLon);
    
    		GraphicsLayer graphicsLayer = MyMap.Layers["GeocodingGraphicsLayer"] as GraphicsLayer;
    		graphicsLayer.ClearGraphics();
    	}
    	else
    	{
    	}
    }
    
  8. Add the new geocoding result to the GraphicsLayer so that it is shown on the Map.
    private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
    {
    	if (args.Results.Count > 0)
    	{
    		AddressCandidate bestCandidate = args.Results[0];
    		foreach (AddressCandidate candidate in args.Results)
    			bestCandidate = (candidate.Score > bestCandidate.Score) ? candidate : bestCandidate;
    
    		Graphic graphic = new Graphic()
    		{
    			Symbol = LayoutRoot.Resources["GeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    			Geometry = bestCandidate.Location
    		};
    
    		graphic.Attributes.Add("Address", bestCandidate.Address);
    		string latLon = String.Format("{0}, {1}", bestCandidate.Location.X, bestCandidate.Location.Y);
    		graphic.Attributes.Add("LatLon", latLon);
    
    		GraphicsLayer graphicsLayer = MyMap.Layers["GeocodingGraphicsLayer"] as GraphicsLayer;
    		graphicsLayer.ClearGraphics();
    		graphicsLayer.Graphics.Add(graphic);
    	}
    	else
    	{
    	}
    }
    
  9. If no features were found, notify the user with a MessageBox.
    private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args)
    {
    	if (args.Results.Count > 0)
    	{
    		AddressCandidate bestCandidate = args.Results[0];
    		foreach (AddressCandidate candidate in args.Results)
    			bestCandidate = (candidate.Score > bestCandidate.Score) ? candidate : bestCandidate;
    
    		Graphic graphic = new Graphic()
    		{
    		 Symbol = LayoutRoot.Resources["GeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    			Geometry = bestCandidate.Location
    		};
    
    		graphic.Attributes.Add("Address", bestCandidate.Address);
    		string latLon = String.Format("{0}, {1}", bestCandidate.Location.X, bestCandidate.Location.Y);
    		graphic.Attributes.Add("LatLon", latLon);
    
    		GraphicsLayer graphicsLayer = MyMap.Layers["GeocodingGraphicsLayer"] as GraphicsLayer;
    		graphicsLayer.ClearGraphics();
    		graphicsLayer.Graphics.Add(graphic);
    	}
    	else
    	{
    		MessageBox.Show("No results found");
    	}
    }
    

Handle reverse geocoding results

  1. Declare a handler for the Address Locator task's LocationToAddressCompleted event. This handler will be invoked when a reverse geocoding operation is complete. The address information for the address closest to the input point is passed to the handler's args parameter.
    private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args)
    {
    }
    
  2. Get references to the found address and its attributes.
    private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args)
    {
    	Address address = args.Address;
    	Dictionary<string, object> attributes = args.Address.Attributes;
    }
    
  3. Create a Graphic to display the address. Initialize it with the result's location and the reverse geocoding result symbol you defined in the window's XAML.
    private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args)
    {
    	Address address = args.Address;
    	Dictionary<string, object> attributes = args.Address.Attributes;
    
    	Graphic graphic = new Graphic()
    	{
    		Symbol = LayoutRoot.Resources["ReverseGeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    		Geometry = address.Location,
    	};
    }
    
  4. Get the coordinates and address of the result and format them for display on the Graphic's MapTip.
    private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args)
    {
    	Address address = args.Address;
    	Dictionary<string, object> attributes = args.Address.Attributes;
    
    	Graphic graphic = new Graphic()
    	{
    		Symbol = LayoutRoot.Resources["ReverseGeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    		Geometry = address.Location,
    	};
    
    	string latLon = String.Format("{0}, {1}", address.Location.X, address.Location.Y);
     string address1 = String.Format("{0}, {1} {2}", attributes["Street"], attributes["State"], attributes["ZIP"]);
    }
    
  5. Add the coordinates and address of the result to the Graphic in attributes named LatLon and Address1. Recall that, in the window's XAML, you specified attributes with these names to be bound to the MapTips of the reverse geocoding GraphicsLayer. So adding the address information to the Graphic with these attributes names will result in this information being displayed on the Graphic's MapTip.
    private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args)
    {
    	Address address = args.Address;
    	Dictionary<string, object> attributes = args.Address.Attributes;
    
    	Graphic graphic = new Graphic()
    	{
    		Symbol = LayoutRoot.Resources["ReverseGeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    		Geometry = address.Location,
    	};
    
    string latLon = String.Format("{0}, {1}", address.Location.X, address.Location.Y);
    string address1 = String.Format("{0}, {1} {2}", attributes["Street"], attributes["State"], attributes["ZIP"]);
    	
    graphic.Attributes.Add("LatLon", latLon);
    graphic.Attributes.Add("Address1", address1);
    
    }
    
  6. Retrieve the reverse geocoding results GraphicsLayer and add the Graphic to it.
    private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args)
    {
    	Address address = args.Address;
    	Dictionary<string, object> attributes = args.Address.Attributes;
    
    	Graphic graphic = new Graphic()
    	{
    		Symbol = LayoutRoot.Resources["ReverseGeocodingSymbol"] as ESRI.ArcGIS.Client.Symbols.MarkerSymbol,
    		Geometry = address.Location,
    	};
    
    	string latLon = String.Format("{0}, {1}", address.Location.X, address.Location.Y);
     string address1 = String.Format("{0}, {1} {2}", attributes["Street"], attributes["State"], attributes["ZIP"]);
    	
     graphic.Attributes.Add("LatLon", latLon);
    	graphic.Attributes.Add("Address1", address1);
    
    	GraphicsLayer graphicsLayer = MyMap.Layers["ReverseGeocodingGraphicsLayer"] as GraphicsLayer;
    	graphicsLayer.Graphics.Add(graphic);
    }
    

Handling execution errors

  1. Declare a handler for the Address Locator task's Failed event. This handler will be invoked if there is a problem with executing a geocoding or reverse geocoding operation.
    private void LocatorTask_Failed(object sender, TaskFailedEventArgs e)
    {
    }
    
  2. Notify the user of the problem with a MessageBox.
    private void LocatorTask_Failed(object sender, TaskFailedEventArgs e)
    {
    	MessageBox.Show("Locator service failed: " + e.Error);
    }
    

The Locator with online data

The Locator can also be performed on online data. To use the sample with online data modify the URL inputted into the Locator constructor to be a URL to an ArcGIS for Server Geocode service. To find a URL, you can use the ArcGIS Services Directory. The example below uses the ESRI USA Geocode Service and the ESRI World Street Map as a base layer

In the click handler for the geocoding operation, pass the online service's URL to the task's constructor. The ESRI USA Geocode Service takes the following address parameters Address, City, State and ZIP. Edit the address parameters to reflect this.

private void FindAddressButton_Click(object sender, RoutedEventArgs e)
{
	Locator locatorTask = new Locator("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/" +
		"Locators/ESRI_Geocode_USA/GeocodeServer");
	locatorTask.AddressToLocationsCompleted += LocatorTask_AddressToLocationsCompleted;
	locatorTask.Failed += LocatorTask_Failed;

	AddressToLocationsParameters addressParameters = new AddressToLocationsParameters();
	Dictionary<string, string> address = addressParameters.Address;

	address.Add("Address", Address.Text);
	address.Add("City", City.Text);
	address.Add("State", State.Text);
	address.Add("Zip", Zip.Text);

	locatorTask.AddressToLocationsAsync(addressParameters);
}

Modify the map control to display an online map service rather than local data.

<!-- MAP -->
		<esri:Map x:Name="MyMap" Extent="-74.18,40.69,-73.89,40.89" >
			<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>

Modify the textboxes in the XAML to reflect the correct attributes and default values for the online Geocode Service.

<StackPanel Margin="10" HorizontalAlignment="Left">
	<Grid>
		<Rectangle Fill="#CC5C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" />
		<StackPanel Margin="10" HorizontalAlignment="Center" >
			<TextBlock Text="Click Find to locate an address" HorizontalAlignment="Center" 
					   Margin="0,0,0,5" Foreground="White" FontStyle="Italic" />
			<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
				<TextBlock Text="Address: " Foreground="White" />
				<TextBox x:Name="Address" Text="1000 Broadway" Width="125" />
			</StackPanel>
			<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
				<TextBlock Text="City: " Foreground="White" />
				<TextBox x:Name="City" Text="New York" Width="125" />
			</StackPanel>
			<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
				<TextBlock Text="State: " Foreground="White" />
				<TextBox x:Name="State" Text="NY" Width="125"/>
			</StackPanel>
			<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
				<TextBlock Text="Zip: " Foreground="White" />
				<TextBox x:Name="Zip" Text="" Width="125" />
			</StackPanel>
			<Button x:Name="FindAddressButton" Content="Find" Width="100" HorizontalAlignment="Center"
					Click="FindAddressButton_Click" Margin="0,5,0,0" />
			<Line HorizontalAlignment="Center" X1="0" Y1="10" X2="180" Y2="10" StrokeThickness="1" Stroke="White" />
			<TextBlock Text="Or click map to retrieve address" FontStyle="Italic" HorizontalAlignment="Center" 
					   Foreground="White" Margin="0,10,0,0" />
		</StackPanel>
	</Grid>
</StackPanel>

In the Map's MouseClick event handler for the reverse geocoding operation, pass the online service's URL to the task's constructor.

private void MyMap_MouseClick(object sender, Map.MouseEventArgs e)
{
	Locator locatorTask = new Locator("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Locators/" +
		"ESRI_Geocode_USA/GeocodeServer");
	locatorTask.LocationToAddressCompleted += LocatorTask_LocationToAddressCompleted;
	locatorTask.Failed += LocatorTask_Failed;

	locatorTask.LocationToAddressAsync(e.MapPoint, 50);
}

To handle the reverse geocoding results from the online Geocode Service the address of the results will have to be formatted for the correct attributes to be displayed in the Graphic's MapTips.

private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args)
{
	Address address = args.Address;
	Dictionary<string, object> attributes = args.Address.Attributes;

	Graphic graphic = new Graphic()
	{
		Symbol = LocationToAddressSymbol,
		Geometry = address.Location,
	};

	string latLon = String.Format("{0}, {1}", address.Location.X, address.Location.Y);
	string address1 = attributes["Address"].ToString();
	string address2 = String.Format("{0}, {1} {2}", attributes["City"], attributes["State"], attributes["Zip"]);

	graphic.Attributes.Add("LatLon", latLon);
	graphic.Attributes.Add("Address1", address1);
	graphic.Attributes.Add("Address2", address2);

	GraphicsLayer graphicsLayer = MyMap.Layers["LocationToAddressGraphicsLayer"] as GraphicsLayer;
	graphicsLayer.Graphics.Add(graphic);

1/27/2015