Click or drag to resize
Code Example - GeocodeFullAddressInput

Demonstrates performing a geocode by submitting values for multiple address fields.

Code Example
Geocode Full Address Input

This section contains selected code files from a Visual Studio project that emphasize specific ArcGIS Runtime SDK (Windows Desktop) features. For example: some code examples may accomplish the bulk of the work as a configuration property in the .xaml file and hence only the .xaml file will be shown in detail below. In other code examples, the .xaml is used to define the configuration of graphical elements for the application but the application logic is performed in the code behind, hence you may see both the .xaml and .cs/.vb files shown in detail below.

XAML
<Window x:Class="GeocodeFullAddressInput.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/runtime/2013" UseLayoutRounding="True"
             Height="600" Width="800">

    <!-- Define the GUI of the sample application. -->
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="3" />
        </Grid.RowDefinitions>

        <!-- Add a MapView. -->
        <esri:MapView x:Name="MapView1" WrapAround="True" Grid.Row="0">

            <!-- Add a Map. -->
            <esri:Map x:Name="MyMap" >

                <!-- Add a backdrop ArcGISTiledMapServiceLayer of streets for the world. Although when the 
                application loads the extent will zoom to the downtown San Diego area. -->
                <esri:ArcGISTiledMapServiceLayer 
                    ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />

                <!-- Create an initial blank GraphicsLayer to hold results of the geocoding operation (i.e. Locatortask). -->
                <esri:GraphicsLayer ID="CandidateAddressesGraphicsLayer" />

            </esri:Map>
        </esri:MapView>

        <Border HorizontalAlignment="Right" VerticalAlignment="Top" Margin="10" Padding="5" Background="White" 
                BorderBrush="Black" BorderThickness="1">
            <Border.Effect>
                <DropShadowEffect />
            </Border.Effect>
            <StackPanel Orientation="Vertical">

                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition />
                        <ColumnDefinition Width="2*"/>
                    </Grid.ColumnDefinitions>

                    <!-- GUI elements that the user will interact with to define how the geocoding will occur:
                    specifically: (1) specifying the address field information, (2) setting minimum match score
                    to display results visually back in the map, and (3) whether to do the geocoding using an
                    online web service or using a local (on disk) locator (.loc) file. -->
                    <TextBlock Text="Enter Address Information" FontWeight="Bold" HorizontalAlignment="Center" Margin="3" 
                           Grid.Row="0" Grid.ColumnSpan="2" />
                    <TextBlock Text="Address: " HorizontalAlignment="Left" VerticalAlignment="Center" Margin="3"
                           TextAlignment="Right" Grid.Row="1" Grid.Column="0"/>
                    <TextBox x:Name="InputAddress" HorizontalAlignment="Stretch" Text="2920 Zoo Dr" Grid.Row="1" Margin="3"
                         Grid.Column="1" />
                    <TextBlock Text="City: " HorizontalAlignment="Left" VerticalAlignment="Center" Margin="3"  
                           Grid.Row="2" Grid.Column="0"
                           TextAlignment="Right" />
                    <TextBox x:Name="City" HorizontalAlignment="Stretch" Text="San Diego"  Grid.Row="2" Margin="3"
                         Grid.Column="1"/>
                    <TextBlock Text="State: " VerticalAlignment="Center" Margin="3"  TextAlignment="Left" 
                           Grid.Row="3" Grid.Column="0"/>
                    <TextBox x:Name="State" Text="CA" Grid.Row="3" Grid.Column="1" Margin="3"/>
                    <TextBlock Text="Zip: " VerticalAlignment="Center" TextAlignment="Left" Margin="3"
                           Grid.Row="4" Grid.Column="0" />
                    <TextBox x:Name="Zip" Text="92101" Grid.Row="4" Grid.Column="1" Margin="3"/>
                </Grid>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                    <TextBlock Text="Match Score:"/>
                    <Slider x:Name="MatchScoreSlider"  Margin="5" Width="100" Orientation="Horizontal" 
                            HorizontalAlignment="Center" Minimum="0" Maximum="100" IsSnapToTickEnabled="True" 
                            AutoToolTipPlacement="BottomRight" AutoToolTipPrecision="2" Value="{Binding MatchScore, Mode=TwoWay}"
                            TickPlacement="BottomRight" TickFrequency="10" Ticks="0, 10, 20, 30, 40, 50, 60, 70, 80, 90 ,100"/>
                </StackPanel>
                <CheckBox IsChecked="True" HorizontalAlignment="Center" Margin="10,5,5,5" Click="CheckBox_Click" 
                          x:Name="CheckBox1">Online?</CheckBox>

                <!-- Button to invoke the geocoding process. The results will display as graphics in the Map. -->
                <Button Content="Find Address" Margin="5" Click="FindButton_Click"
                        HorizontalAlignment="Center" Width="100" Height="25" />

            </StackPanel>
        </Border>
    </Grid>

</Window>

SPECIAL NOTE: The XAML displayed above comes from a C# project. If you are a VB.NET developer, you will need to modify the text for the x:Class namespace from "GeocodeFullAddressInput.MainWindow" to be just "MainWindow".

using System;
using System.Linq;

// NOTE: This sample demonstrates performing a geocode by submitting values for multiple address fields. Some MVVM styles of
// programming logic are incorporated for control updates within the application. 
// 
// TO USE: 
// (1) Using the default values set in the GUI, click the 'Find Address' button to obtain geocode results via the online 
// (i.e. web service ) LocatorTask. The map will automatically zoom to the results of the matched addresses. Then adjust the 
// slider to see the effect of relaxing the match score of the geocoding when displaying the Graphics. 
// (2) Then uncheck the 'Offline' Checkbox and push the 'Find Address' button again. This time the offline (i.e. local
// disk) locator file (.loc) is used to obtain geocoding results will be used. Note: The geocoding results will differ 
// as compared to the online web service. Again the map will zoom to the extent of the geocoding results. Also adjust 
// the slider to see the effect of the match score changes. 
// (3) If you know other addresses in San Diego, experiment with changing the various fields and re-run the geocoding 
// AddressLocator in both the online and offline mode. 

namespace GeocodeFullAddressInput
{

    // Inherit the functionality from the basic Window Class.
    // Enable adding the functionality of INotifyPropertyChanged interface into the sample. We will use it for updating
    // changes when the user switches doing geocoding online or offline and when the match score of the geocoding is 
    // adjusted.
    public partial class MainWindow : System.Windows.Window, System.ComponentModel.INotifyPropertyChanged
    {
        // Declare the signature of the PropertyChanged Event when various property values change.
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;


        // Global variable for determining if online or offline geocoding will occur.
        private bool _isOnline = true;

        // Gets or sets a value indicating whether this instance is online. True if this instance is online; otherwise, False.
        public bool IsOnline
        {
            get
            {
                return _isOnline;
            }
            set
            {
                _isOnline = value;

                // Call the function to set up the Locator Task as to whether it will be online or offline.
                SetupLocator();

                if (PropertyChanged != null)
                    PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("IsOnline"));
            }
        }


        // Global variable for determining match score of the geocoding.
        private double _matchScore = 100;

        // Gets or sets the match score.
        public double MatchScore
        {
            get
            {
                return _matchScore;
            }
            set
            {
                _matchScore = value;

                // Update the list of graphic to display only those that meet the match score or higher.
                UpdateCandidateGraphics();

                if (PropertyChanged != null)
                    PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("MatchScore"));
            }
        }

        // Global variable for LocatorTask (aka. Geocoding).
        private Esri.ArcGISRuntime.Tasks.Geocoding.LocatorTask _locatorTask;

        // Global variable to hold the list of LocatorGeocodeResult (aka. matched results) from the geocoding operation.
        private System.Collections.Generic.IList<Esri.ArcGISRuntime.Tasks.Geocoding.LocatorGeocodeResult> _candidateResults;

        // Global variable to hold the graphics for each of the matched results from the geocoding operation.
        private Esri.ArcGISRuntime.Layers.GraphicsLayer _candidateAddressesGraphicsLayer;


        public MainWindow()
        {
            InitializeComponent();

            // Set up the Binding DataContent to this application.
            DataContext = this;

            // Define a SpatialReference for WebMercator.
            Esri.ArcGISRuntime.Geometry.SpatialReference spatialReferenceWebMercator = null;
            spatialReferenceWebMercator = new Esri.ArcGISRuntime.Geometry.SpatialReference(102100);

            // Define an Envelope for the downtown San Diego region using the WebMercator SpatialReference.
            Esri.ArcGISRuntime.Geometry.Envelope myEnvelope = null;
            myEnvelope = new Esri.ArcGISRuntime.Geometry.Envelope(-13044000, 3855000, -13040000, 3858000, spatialReferenceWebMercator);

            // Set the initial extent of the Map using the InitialViewpoint Property to the downtown San Diego region.
            MapView1.Map.InitialViewpoint = new Esri.ArcGISRuntime.Controls.Viewpoint(myEnvelope);

            // Call the function to set up the Locator Task as to whether it will be online or offline.
            SetupLocator();

            // Get the GraphicsLayer defined in XAML and assign it to the global variable used to display matched results on the Map.
            _candidateAddressesGraphicsLayer = MyMap.Layers["CandidateAddressesGraphicsLayer"] as Esri.ArcGISRuntime.Layers.GraphicsLayer;

            // Call the function that sets up the symbology for the matched results of the geocoding operation.
            System.Threading.Tasks.Task setSimpleRendererSymbolsTask = SetSimpleRendererSymbols();
        }

        private async System.Threading.Tasks.Task SetSimpleRendererSymbols()
        {
            // Define a new PictureMarkerSymbol that will be used to display the symbology for matched results on the Map. 
            Esri.ArcGISRuntime.Symbology.PictureMarkerSymbol findResultMarkerSymbol = new Esri.ArcGISRuntime.Symbology.PictureMarkerSymbol();

            // Specify the Height, Width, and Offset of the PictureMarkerSymbol.
            findResultMarkerSymbol.Width = 48;
            findResultMarkerSymbol.Height = 48;
            findResultMarkerSymbol.YOffset = 24;

            // Set the source of the PictureMarkerSymbol to be a .png included in this sample. 
            // NOTE: There are numerous ways to reference local resources in a Uri, this example demonstrates just one way.
            // The following MSDN article provides a comprehensive discussion using Pack Uri's in WPF:
            //http://msdn.microsoft.com/en-us/library/aa970069.aspx 
            Uri myUri = new Uri("pack://application:,,,/GeocodeFullAddressInput;component/Assets/RedStickpin.png");
            await findResultMarkerSymbol.SetSourceAsync(myUri);

            // Define a new SimpleRenderer that will hold the PictureMarkerSymbol to display the geocoding results.
            Esri.ArcGISRuntime.Symbology.SimpleRenderer findResultRenderer = new Esri.ArcGISRuntime.Symbology.SimpleRenderer();

            // Specify the symbol of the SimpleRenderer to the PictureMarkerSymbol.
            findResultRenderer.Symbol = findResultMarkerSymbol;

            // Apply the SimpleRenderer just defined for the GraphicsLayer that will display the results of geocoding matches.
            _candidateAddressesGraphicsLayer.Renderer = findResultRenderer;
        }

        private void SetupLocator()
        {
            // This function will determine if the online or offline geocoding LocatorTask will be used.

            try
            {
                if (! IsOnline)
                {
                    // Use the offline geocoding LocatorTask.
                    _locatorTask = new Esri.ArcGISRuntime.Tasks.Geocoding.LocalLocatorTask("..\\..\\locators\\san-diego\\san-diego-locator.loc");
                }
                else
                {
                    // Use the online (i.e. a web service) geocoding LocatorTask. 
                    _locatorTask = new Esri.ArcGISRuntime.Tasks.Geocoding.OnlineLocatorTask(new Uri("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer"), string.Empty);
                }
            }
            catch (Exception ex)
            {
                // There was problem accessing the geocoding LocatorTask. Notify the user.
                System.Windows.MessageBox.Show(ex.ToString());
            }
        }

        private async void FindButton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            // This function executes each time the user clicks the button to perform a geocoding operation.

            // Clear out any existing graphics in the display if the user hits the button multiple times.
            _candidateAddressesGraphicsLayer.Graphics.Clear();

            try
            {
                // Get the general information about the LocatorService.
                Esri.ArcGISRuntime.Tasks.Geocoding.LocatorServiceInfo myLocatorServiceInfo = await _locatorTask.GetInfoAsync();

                // Define the Dictionary of key/value pairs that serve as input for the geocoding search.
                System.Collections.Generic.Dictionary<string, string> addressInputParametersDictionary = new System.Collections.Generic.Dictionary<string, string>();

                // Populate the Dictionary with the key/value pairs based upon the user settings in the GUI of the application.
                if (! (string.IsNullOrEmpty(InputAddress.Text)))
                {
                    string fieldName = ((_isOnline == true) ? "Address" : "Street");
                    addressInputParametersDictionary.Add(fieldName, InputAddress.Text);
                }
                if (! (string.IsNullOrEmpty(City.Text)))
                {
                    string fieldName = ((_isOnline == true) ? "City" : "City");
                    addressInputParametersDictionary.Add(fieldName, City.Text);
                }
                if (! (string.IsNullOrEmpty(State.Text)))
                {
                    string fieldName = ((_isOnline == true) ? "Region" : "State");
                    addressInputParametersDictionary.Add(fieldName, State.Text);
                }
                if (! (string.IsNullOrEmpty(Zip.Text)))
                {
                    string fieldName = ((_isOnline == true) ? "Postal" : "ZIP");
                    addressInputParametersDictionary.Add(fieldName, Zip.Text);
                }

                // Call the asynchronous LocatorTask.GeocodeAsync Method which will perform geocoding using either the 
                // online or offline source and return the results.
                _candidateResults = await _locatorTask.GeocodeAsync(addressInputParametersDictionary, new System.Collections.Generic.List<string>() {"Match_addr"}, MapView1.SpatialReference, System.Threading.CancellationToken.None);

                // Define a new List of Graphics that will be used to hold the results of the LocatorGeocodeResult objects.
                System.Collections.Generic.List<Esri.ArcGISRuntime.Layers.Graphic> candidategraphicsList = null;
                candidategraphicsList = new System.Collections.Generic.List<Esri.ArcGISRuntime.Layers.Graphic>();

                // Define an envelope that will be used to hold the spatial extent of all the matched candidates from the 
                // geocoding operation. This envelope will be used to zoom to Map to the extent of the matched geocode
                // results.
                Esri.ArcGISRuntime.Geometry.Envelope resultsEnvelope = null;

                // Loop through each geocode match result (i.e. LocatorGeocodeResult) in the list of matches.
                foreach (Esri.ArcGISRuntime.Tasks.Geocoding.LocatorGeocodeResult candidate in _candidateResults)
                {
                    // Define a MapPoint based upon the geocode result.
                    Esri.ArcGISRuntime.Geometry.MapPoint myMapPoint = candidate.Location;

                    // Define a new Graphic based upon the MapPoint.
                    Esri.ArcGISRuntime.Layers.Graphic myGraphic = new Esri.ArcGISRuntime.Layers.Graphic();
                    myGraphic.Geometry = myMapPoint;

                    // Add attributes to the Graphic from various information in the geocode match.
                    myGraphic.Attributes.Add("Match_addr", candidate.Attributes["Match_addr"]);
                    myGraphic.Attributes.Add("Score", candidate.Score);
                    string latlon = string.Format("{0}, {1}", candidate.Location.X, candidate.Location.Y);
                    myGraphic.Attributes.Add("LatLon", latlon);

                    // Add the Graphic to the list of Graphics that should the results of the geocoding operation.
                    candidategraphicsList.Add(myGraphic);

                    // Set an initial extent of the envelope that shows where the geocoding results are occurring.
                    if (resultsEnvelope == null)
                    {
                        resultsEnvelope = new Esri.ArcGISRuntime.Geometry.Envelope(candidate.Location, candidate.Location);
                    }
                }

                // Add the geocoded Graphics to the GraphicsLayer that will display in the Map.
                _candidateAddressesGraphicsLayer.Graphics.AddRange(candidategraphicsList);

                // Call the function that will display only those graphics in the GraphicsLayer that have a minimum
                // match score determined by the slider in the GUI.
                UpdateCandidateGraphics();

                // Zoom the extent of the MapView to the extent of the matched geocode results that meet the minimum matched score.
                if (resultsEnvelope != null)
                {
                    await MapView1.SetViewAsync(resultsEnvelope.Expand(2));
                }
                else
                {
                    await MapView1.SetViewAsync(_candidateResults.First(x => x.Score == 100).Extent.Expand(2));
                }

            }
            catch (AggregateException ex)
            {

                // There were problems in the geocoding. Display the results to the user.
                var innermostExceptions = ex.Flatten().InnerExceptions;
                if (innermostExceptions != null && innermostExceptions.Count > 0)
                {
                    System.Windows.MessageBox.Show(string.Join(" > ", innermostExceptions.Select(i => i.Message).ToArray()));
                }
                else
                {
                    System.Windows.MessageBox.Show(ex.Message);
                }
            }
            catch (System.Exception ex)
            {

                // There were problems in the geocoding. Display the results to the user.
                System.Windows.MessageBox.Show(ex.Message);

            }
        }

        private void UpdateCandidateGraphics()
        {
            // Restrict the visibility of the match results from the geocoding operation based upon the match score
            // that the user adjusts in the slider on the GUI.

            foreach (Esri.ArcGISRuntime.Layers.Graphic g in _candidateAddressesGraphicsLayer.Graphics)
            {
                if (Convert.ToDouble(g.Attributes["Score"]) < MatchScore)
                {
                    g.IsVisible = false;
                }
                else
                {
                    g.IsVisible = true;
                }
            }
        }

        private void CheckBox_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            // Update whether the geocoding engine used to generate match results will be based upon occur online or offline.

            if (CheckBox1.IsChecked == true)
            {
                IsOnline = true;
            }
            else if (CheckBox1.IsChecked == false)
            {
                IsOnline = false;
            }
        }
    }
}