Address Locator task
The Address Locator task allows you to perform geocoding and reverse geocoding operations. Geocoding takes an address and returns the geographic location of that address. In reverse geocoding, a geographic location is provided and an address that matches it is returned. Once the location or address is returned, you can use .NET code to display the information in your application. To use an Address Locator task, you need to include code to define its user interface (UI) and specify its execution logic.
Samples of Address Locator task applications, including both geocoding and reverse geocoding, are available in the Address Matching section of the Interactive SDK.
Creating an Address Locator task
The following sections walk you through building an example of XAML and .NET code (in this case C#) for a simple Windows Phone application that includes an Address Locator task:
- Creating an input interface for the Address Locator task
- Creating an output interface for the Address Locator task
- Implementing the Address Locator task's execution logic
This application defines an Address Locator task that uses a set of TextBox controls to specify input and a button for geocoding, along with executing reverse geocoding when the user taps and holds the map. The resulting geocoding feature is displayed in a GraphicsLayer, while the address determined by reverse geocoding is displayed in the TextBoxes.
The following sections assume you have created a Windows Phone application with a map as a base layer as described in Creating a map. The XAML view of your application's ContentPanel in MainPage.xaml should look like the following code:
<Grid x:Name="ContentPanel" Grid.Row="1">
<esri:Map x:Name="MyMap" Extent="-120, 20, -100, 40">
<esri:Map.Layers>
<esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"
Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer">
</esri:ArcGISTiledMapServiceLayer>
</esri:Map.Layers>
</esri:Map>
</Grid>
In the following example code, the extent of the Map was changed to "-117.20, 34.04, -117.18, 34.06" to display Redlands, California, at the street level.
The code in your code-behind file, MainPage.xaml.cs, should be unchanged from when you created your Windows Phone project in Visual Studio.
Creating an input interface for the Address Locator task
Tasks do not define UIs, so it's up to you as a developer to implement an interface for the Address Locator's input. For geocoding input, you'll define a TextBlock for instructions, TextBoxes for the address information, and a Button to start the operation. For reverse geocoding, you'll specify a TextBlock for instructions and a handler for the Map's MapGesture event.
- 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 x:Name="InfoPanel" Margin="10" HorizontalAlignment="Left"> <Grid> <Rectangle Fill="#CC5C90B2" Stroke="Gray" RadiusX="10" RadiusY="10" /> <StackPanel Margin="10" HorizontalAlignment="Center" > </StackPanel> </Grid> </StackPanel>
- 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'll implement this handler so that it processes the user input and starts the geocoding operation.
<StackPanel x:Name="InfoPanel" 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="380 New York St." Width="325"/> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" > <TextBlock Text="City: " Foreground="White" /> <TextBox x:Name="City" Text="Redlands" Width="325" /> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" > <TextBlock Text="State: " Foreground="White" /> <TextBox x:Name="State" Text="CA" Width="325"/> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" > <TextBlock Text="Zip: " Foreground="White" /> <TextBox x:Name="Zip" Text="92373" Width="325" /> </StackPanel> <Button x:Name="FindAddressButton" Content="Find" Width="100" HorizontalAlignment="Center" Click="FindAddressButton_Click" Margin="0,5,0,0" /> </StackPanel> </Grid> </StackPanel>
- Specify instructions for reverse geocoding. Add a separator line below the geocoding interface and a TextBlock containing the instructions.
<StackPanel x:Name="InfoPanel" 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="380 New York St." Width="325"/> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" > <TextBlock Text="City: " Foreground="White" /> <TextBox x:Name="City" Text="Redlands" Width="325" /> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" > <TextBlock Text="State: " Foreground="White" /> <TextBox x:Name="State" Text="CA" Width="325"/> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" > <TextBlock Text="Zip: " Foreground="White" /> <TextBox x:Name="Zip" Text="92373" Width="325" /> </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="280" Y2="10" StrokeThickness="1" Stroke="White" /> <TextBlock Text="Or tap and hold the map to retrieve address." FontStyle="Italic" HorizontalAlignment="Center" Foreground="White" Margin="0,10,0,0" /> </StackPanel> </Grid> </StackPanel>
- Since the input interface takes up a large amount of the screen, add an application bar icon that shows and hides the input interface. Replace the sample ApplicationBar XAML with the following code:
<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton IconUri="list.png" Text="Info view"/> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>
Note:You need to add the icon's image file to your project and set the icon image's Build Action property to Content.
- Add a click event handler for the ApplicationBar icon.
<shell:ApplicationBarIconButton IconUri="list.png" Text="Info view" Click="ApplicationBarIconButton_Click"/>
- Implement the click event for the ApplicationBar's icon button in the code-behind, showing and hiding the address information panel, InfoPanel.
private void ApplicationBarIconButton_Click(object sender, EventArgs e) { if (InfoPanel.Visibility == System.Windows.Visibility.Collapsed) InfoPanel.Visibility = System.Windows.Visibility.Visible; else InfoPanel.Visibility = System.Windows.Visibility.Collapsed; }
- Specify instructions for showing and hiding the InfoPanel. Add a separator line below the reverse geocoding instructions, along with a TextBlock containing the instructions for the InfoPanel.
<StackPanel x:Name="InfoPanel" 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="380 New York St." Width="325"/> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" > <TextBlock Text="City: " Foreground="White" /> <TextBox x:Name="City" Text="Redlands" Width="325" /> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" > <TextBlock Text="State: " Foreground="White" /> <TextBox x:Name="State" Text="CA" Width="325"/> </StackPanel> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" > <TextBlock Text="Zip: " Foreground="White" /> <TextBox x:Name="Zip" Text="92373" Width="325" /> </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="280" Y2="10" StrokeThickness="1" Stroke="White" /> <TextBlock Text="Or tap and hold the map to retrieve address." FontStyle="Italic" HorizontalAlignment="Center" Foreground="White" Margin="0,10,0,0" /> <Line HorizontalAlignment="Center" X1="0" Y1="10" X2="280" Y2="10" StrokeThickness="1" Stroke="White" /> <TextBlock Text="Use the app bar to show or hide this panel." FontStyle="Italic" HorizontalAlignment="Center" Foreground="White" Margin="0,10,0,0" /> </StackPanel> </Grid> </StackPanel>
- On the Map control, specify a handler for the MapGesture event. You'll implement this handler later so that it uses the tap and hold location
to initiate a reverse geocoding operation.
<esri:Map x:Name="MyMap" Extent="-117.20, 34.04, -117.18, 34.06" MapGesture="MyMap_MapGesture" >
Creating an output interface for the Address Locator task
To display a task's results, you need to specify an output interface. For geocoding, the location of the address will be displayed on the map as a blue circle using a GraphicsLayer and a SimpleMarkerSymbol. For reverse geocoding, the matching address will be displayed in the TextBoxes that were used for input.
You can also display information about the result; however, for simplicity in this code, that is not shown here.
- Add a reference to the System.Runtime.Serialization assembly to your project.
- Add a namespace reference to the ESRI.ArcGIS.Client.Symbols namespace in the ESRI.ArcGIS.Client assembly by inserting the attribute shown in the following code as an attribute of the phone:PhoneApplicationPageelement in the XAML.
xmlns:esriSymbols="clr-namespace:ESRI.ArcGIS.Client.Symbols;assembly=ESRI.ArcGIS.Client"
- Add a SimpleMarkerSymbol as a resource by adding it to the LayoutRoot grid of your application. The symbol specified here is a blue circle. Later in this topic, you'll apply this symbol to the task's results in the page's code-behind.
<Grid.Resources> <esriSymbols:SimpleMarkerSymbol x:Key="ResultsSymbol" Size="15" Color="Blue" /> </Grid.Resources>
- Add a GraphicsLayer to the Map control XAML element. Make sure it's placed below the map service layer in the XAML so that it's drawn above the map service layer at run time. For further information, see Adding layers.
<esri:Map x:Name="MyMap" Extent="-117.20, 34.04, -117.18, 34.06" MapGesture="MyMap_MapGesture"> <esri:Map.Layers> <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer" Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"> </esri:ArcGISTiledMapServiceLayer> <esri:GraphicsLayer ID="MyGraphicsLayer" > </esri:GraphicsLayer> </esri:Map.Layers> </esri:Map>
Implementing the Address Locator task's execution logic
Now that you've specified the Address Locator task's UI, you need to define its execution logic. The execution logic required for this Address Locator example is described in the following sections:
- Initiating a geocoding operation
- Initiating a reverse geocoding operation
- Handling geocoding results
- Handling reverse geocoding results
- Handling execution errors
As previously mentioned, this task can perform both geocoding and reverse geocoding. In the following sections, you'll implement the Find button's click event handler to initiate a geocoding operation by calling the task's AddressToLocationsAsync method. Then you'll define a handler for the map's MapGesture 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 code-behind file for your Windows Phone application's main page (for example, MainPage.xaml.cs). 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.
Initiating a geocoding operation
- In the code-behind class of your application's main page, implement
a handler for the FindAddressButton's click event. You
declared this handler when you defined the FindAddressButton
control in the page's XAML.
private void FindAddressButton_Click(object sender, RoutedEventArgs e) { }
- Add a using statement for the ESRI.ArcGIS.Client.Tasks namespace.
- In the click handler, declare and instantiate an Address Locator
task. Set the geocode service that the task will use to lookup
addresses by passing the service's URL to the 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
ESRI_Geocode_USA service.
private void FindAddressButton_Click(object sender, RoutedEventArgs e) { Locator locatorTask = new Locator("http://sampleserver1.arcgisonline.com/ArcGIS/" + "rest/services/Locators/ESRI_Geocode_USA/GeocodeServer"); }
- Specify a handler for the task's AddressToLocationsCompleted event.
The method specified will be called when the Address Locator task has completed a geocode operation. You'll implement this
handler in the Handling geocoding results section.
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; }
- Specify a handler for the task's Failed event, which fires when
there's a problem performing a geocoding or reverse geocoding
operation. You'll define this handler in the Handling execution errors section.
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; }
- 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) { 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(); }
- Retrieve the address information from the input TextBoxes you
specified in the page's XAML and use it to initialize the parameter
object's Address property.
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); }
- Execute the geocoding operation with the specified address.
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); }
Initiating a reverse geocoding operation
- In the code-behind class of the application's main page, implement
a handler for the map's MapGesture event, responding if the map is tapped and held. You declared
this handler when you specified its name on the Map
element in the page's XAML.
private void MyMap_MapGesture(object sender, ESRI.ArcGIS.Client.Map.MapGestureEventArgs e) { if (e.Gesture == ESRI.ArcGIS.Client.GestureType.Hold) { } }
- In the handler, declare and instantiate an Address Locator task.
Set the geocode service that the task will use to lookup addresses
by passing the service's URL to the 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 ESRI_Geocode_USA service.
private void MyMap_MapGesture(object sender, ESRI.ArcGIS.Client.Map.MapGestureEventArgs e) { if (e.Gesture == ESRI.ArcGIS.Client.GestureType.Hold) { Locator locatorTask = new Locator("http://sampleserver1.arcgisonline.com/ArcGIS/" + "rest/services/Locators/ESRI_Geocode_USA/GeocodeServer"); } }
- Specify a handler for the task's LocationToAddressCompleted event.
The method specified will be called when the Address Locator task
has completed a reverse geocode operation. You'll implement
this handler in the Handling reverse geocoding results section.
private void MyMap_MapGesture(object sender, ESRI.ArcGIS.Client.Map.MapGestureEventArgs e) { if (e.Gesture == ESRI.ArcGIS.Client.GestureType.Hold) { Locator locatorTask = new Locator("http://sampleserver1.arcgisonline.com/ArcGIS/" + "rest/services/Locators/ESRI_Geocode_USA/GeocodeServer"); locatorTask.LocationToAddressCompleted += LocatorTask_LocationToAddressCompleted; } }
- Specify a handler for the task's Failed event, which fires when
there's a problem performing a geocoding or reverse geocoding
operation. You'll define this handler in the Handling execution errors section.
private void MyMap_MapGesture(object sender, ESRI.ArcGIS.Client.Map.MapGestureEventArgs e) { if (e.Gesture == ESRI.ArcGIS.Client.GestureType.Hold) { Locator locatorTask = new Locator("http://sampleserver1.arcgisonline.com/ArcGIS/" + "rest/services/Locators/ESRI_Geocode_USA/GeocodeServer"); locatorTask.LocationToAddressCompleted += LocatorTask_LocationToAddressCompleted; locatorTask.Failed += LocatorTask_Failed; } }
- Execute the reverse geocoding operation to find the address at the
location held on the map. Specify a tolerance of 20 for the
operation. This means that the task will search within 20
meters of the touch location to find the nearest address.
private void MyMap_MapGesture(object sender, ESRI.ArcGIS.Client.Map.MapGestureEventArgs e) { if (e.Gesture == ESRI.ArcGIS.Client.GestureType.Hold) { 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, 20); } }
Handling geocoding results
- 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) { }
- Check whether any results were found.
private void LocatorTask_AddressToLocationsCompleted(object sender, ESRI.ArcGIS.Client.Tasks.AddressToLocationsEventArgs args) { if (args.Results.Count > 0) { } else { } }
- 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 { } }
- Add using statements for the ESRI.ArcGIS.Client and ESRI.ArcGIS.Client.Symbols namespaces.
- Create a Graphic to display the best match on the map. Initialize
it with the result's location and the ResultsSymbol you
defined in the page'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["ResultsSymbol"] as Symbol, Geometry = bestCandidate.Location }; } else { } }
- 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["ResultsSymbol"] as Symbol, Geometry = bestCandidate.Location }; GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer; graphicsLayer.ClearGraphics(); } else { } }
- Add the new geocoding result to the GraphicsLayer so that it's
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["ResultsSymbol"] as Symbol, Geometry = bestCandidate.Location }; GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer; graphicsLayer.ClearGraphics(); graphicsLayer.Graphics.Add(graphic); } else { } }
- Collapse the InfoPanel so the result is not covered on the screen, and pan to the result.
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["ResultsSymbol"] as Symbol, Geometry = bestCandidate.Location }; GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer; graphicsLayer.ClearGraphics(); graphicsLayer.Graphics.Add(graphic); InfoPanel.Visibility = System.Windows.Visibility.Collapsed; MyMap.PanTo(bestCandidate.Location); } else { } }
- 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["ResultsSymbol"] as Symbol, Geometry = bestCandidate.Location }; GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer; graphicsLayer.ClearGraphics(); graphicsLayer.Graphics.Add(graphic); InfoPanel.Visibility = System.Windows.Visibility.Collapsed; MyMap.PanTo(bestCandidate.Location); } else { MessageBox.Show("No results found"); } }
Although not shown in the above-referenced code, it can be useful to provide the user with the address of the best match, as well as information about its latitude and longitude. The following code gives an example of setting the address and coordinates to attributes on the graphic, which could then be bound to an element for display:
graphic.Attributes.Add("Address", bestCandidate.Address);
string latLon = String.Format("{0}, {1}", bestCandidate.Location.X, bestCandidate.Location.Y);
graphic.Attributes.Add("LatLon", latLon);
Handling reverse geocoding results
- 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) { }
- 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 = address.Attributes; }
- Create a Graphic to display the address. Initialize it with the
result's location and the result symbol you
defined in the page's XAML.
private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args) { Address address = args.Address; Dictionary<string, object> attributes = address.Attributes; Graphic graphic = new Graphic() { Symbol = LayoutRoot.Resources["ResultsSymbol"] as Symbol, Geometry = address.Location, }; }
- Add the address information of the result to the InfoPanel and make sure it's visible.
private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args) { Address address = args.Address; Dictionary<string, object> attributes = address.Attributes; Graphic graphic = new Graphic() { Symbol = LayoutRoot.Resources["ResultsSymbol"] as Symbol, Geometry = address.Location, }; Address.Text = attributes["Address"].ToString(); City.Text = attributes["City"].ToString(); State.Text = attributes["State"].ToString(); Zip.Text = attributes["Zip"].ToString(); InfoPanel.Visibility = System.Windows.Visibility.Visible; }
- Retrieve the reverse geocoding results GraphicsLayer, clear it, and add the
Graphic to it.
private void LocatorTask_LocationToAddressCompleted(object sender, AddressEventArgs args) { Address address = args.Address; Dictionary<string, object> attributes = address.Attributes; Graphic graphic = new Graphic() { Symbol = LayoutRoot.Resources["ResultsSymbol"] as Symbol, Geometry = address.Location, }; Address.Text = attributes["Address"].ToString(); City.Text = attributes["City"].ToString(); State.Text = attributes["State"].ToString(); Zip.Text = attributes["Zip"].ToString(); InfoPanel.Visibility = System.Windows.Visibility.Visible; GraphicsLayer graphicsLayer = MyMap.Layers["MyGraphicsLayer"] as GraphicsLayer; graphicsLayer.ClearGraphics(); graphicsLayer.Graphics.Add(graphic); }
Handling execution errors
- Declare a handler for the Address Locator task's Failed event. This
handler will be invoked if there's a problem with executing a
geocoding or reverse geocoding operation.
private void LocatorTask_Failed(object sender, TaskFailedEventArgs e) { }
- Notify the user of the problem with a MessageBox.
private void LocatorTask_Failed(object sender, TaskFailedEventArgs e) { MessageBox.Show("Locator service failed: " + e.Error); }