Click or drag to resize
Code Example - RoutingPointToPoint

Demonstrates simple point to point routing between two input locations.

Code Example
Routing Point To Point

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="RoutingPointToPoint.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"
        Height="600" Width="800">

    <Grid>

        <!-- Add a MapView Control. -->
        <esri:MapView x:Name="MapView1">

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

                <!-- Add a backdrop ArcGISTiledMapServiceLayer that shows street networks. -->
                <esri:ArcGISTiledMapServiceLayer
            ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
            </esri:Map>
        </esri:MapView>

        <!-- Define the GUI for the user to perform Routing Point to Point. -->
        <Border HorizontalAlignment="Right" VerticalAlignment="Top" Margin="10" Padding="5" Background="White" 
                BorderBrush="Black" BorderThickness="1">
            <Border.Effect>
                <DropShadowEffect />
            </Border.Effect>
            <StackPanel Orientation="Vertical">
                <TextBlock Text="Click the button then define two locations on the Map to calculate a simple route."></TextBlock>

                <StackPanel Orientation="Horizontal">
                    <TextBlock Margin="5" Width="50" Text="Start:"></TextBlock>
                    <TextBox x:Name="StartLocationTextBox" Margin="5" Width="250" Text="{Binding Path=StartLocationText}" />
                </StackPanel>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Margin="5" Width="50" Text="End:"></TextBlock>
                    <TextBox x:Name="EndLocationTextBox" Margin="5" Width="250" Text="{Binding Path=EndLocationText}" />
                </StackPanel>

                <StackPanel Orientation="Horizontal">

                    <!-- Button to allow uses to add point graphics on the Map for with routing will occur. -->
                    <Button Content="Add Start / End Locations" IsEnabled="{Binding Path=IsMapReady}" x:Name="SolveRouteButton" 
                        Margin="5" Click="SolveRouteButton_Click" Width="150" Height="25" />

                </StackPanel>

            </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 "RoutingPointToPoint.MainWindow" to be just "MainWindow".

using System.Linq;

// NOTE: This sample demonstrates performing a routing between two points via user mouse clicks on the Map. Some MVVM styles of
// programming logic are incorporated for control updates within the application. 
// 
// TO USE: 
// When the application loads, click the 'Add Start/End Locations' button. Then click on the Map to specify the start route 
// location. Then click on the Map again to specify the end route location. The RouteTask operation will run and return a 
// polyline route displayed back on the Map. This will perform a RouteTask using the Online web service.

namespace RoutingPointToPoint
{

    public partial class MainWindow : System.Windows.Window, System.ComponentModel.INotifyPropertyChanged
    {

        // Inherit the functionality from the basic Window Class.

        // Enable adding the functionality of INotifyPropertyChanged interface into the sample. We will use it for 
        // determining if the Map is ready for adding graphics, and setting routing
        // starting and ending locations text in the TextBoxes.

        // Declare the signature of the PropertyChanged Event when various property values change.
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;


        // Global variable for determining if the Map is ready for adding graphics.
        private bool _isMapReady = false;

        // Gets or sets a value indicating whether the Map is initialized. True if the Map is initialized; otherwise, False.
        public bool IsMapReady
        {
            get
            {
                return _isMapReady;
            }
            set
            {
                _isMapReady = value;

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



        // Global variable used for updating the start location text.
        private string _startLocationText = "";

        // Get or set the text indicating the coordinate location text for the starting location of the route.
        public string StartLocationText
        {
            get
            {
                return _startLocationText;
            }
            set
            {
                _startLocationText = value;

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

        private string _endLocationText = "";

        /// <summary>
        /// Gets or sets the end location text.
        /// </summary>
        /// <value>
        /// The end location text.
        /// </value>
        public string EndLocationText
        {
            get
            {
                return _endLocationText;
            }
            set
            {
                _endLocationText = value;

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

        // Global variable for the polyline route GraphicsLayer displayed to the user in the Map. 
        Esri.ArcGISRuntime.Layers.GraphicsLayer _routeGraphicsLayer;

        // Global variable for the beginning and ending points GraphicsLayer when the user clicks on the Map.
        Esri.ArcGISRuntime.Layers.GraphicsLayer _stopsGraphicsLayer;

        // Global variable for the RouteTask. 
        Esri.ArcGISRuntime.Tasks.NetworkAnalyst.RouteTask _routeTask;

        private void SetupRouteTask()
        {
            // This function sets up the _routeTask.
            string onlineRoutingService = "http://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/Route";
            _routeTask = new Esri.ArcGISRuntime.Tasks.NetworkAnalyst.OnlineRouteTask(new System.Uri(onlineRoutingService));
        }

        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 (via the InitialViewpoint Property) of the Map to the downtown San Diego region.
            MapView1.Map.InitialViewpoint = new Esri.ArcGISRuntime.Controls.Viewpoint(myEnvelope);

            // Call the function to set up the Route Task.
            SetupRouteTask();

            // Create a new GraphicsLayer to hold the polyline route.
            _routeGraphicsLayer = new Esri.ArcGISRuntime.Layers.GraphicsLayer();

            // Create a new renderer to symbolize the polyline and apply it to the GraphicsLayer
            Esri.ArcGISRuntime.Symbology.SimpleLineSymbol myPolylineRouteSymbol = new Esri.ArcGISRuntime.Symbology.SimpleLineSymbol();
            myPolylineRouteSymbol.Color = System.Windows.Media.Colors.Blue;
            myPolylineRouteSymbol.Style = Esri.ArcGISRuntime.Symbology.SimpleLineStyle.Dot;
            myPolylineRouteSymbol.Width = 2;
            Esri.ArcGISRuntime.Symbology.SimpleRenderer myPolylineRouteRenderer = new Esri.ArcGISRuntime.Symbology.SimpleRenderer();
            myPolylineRouteRenderer.Symbol = myPolylineRouteSymbol;
            _routeGraphicsLayer.Renderer = myPolylineRouteRenderer;

            // Add the polyline route GraphicsLayer to the LayerCollection in the Map.
            MapView1.Map.Layers.Add(_routeGraphicsLayer);

            // Create a new GraphicsLayer to hold the start and end point locations of the route.
            _stopsGraphicsLayer = new Esri.ArcGISRuntime.Layers.GraphicsLayer();

            // Create a new renderer to symbolize the start and end points that define the route and apply it to the GraphicsLayer
            Esri.ArcGISRuntime.Symbology.SimpleMarkerSymbol myStopSymbol = new Esri.ArcGISRuntime.Symbology.SimpleMarkerSymbol();
            myStopSymbol.Color = System.Windows.Media.Colors.Green;
            myStopSymbol.Size = 12;
            myStopSymbol.Style = Esri.ArcGISRuntime.Symbology.SimpleMarkerStyle.Circle;
            Esri.ArcGISRuntime.Symbology.SimpleRenderer myStopRenderer = new Esri.ArcGISRuntime.Symbology.SimpleRenderer();
            myStopRenderer.Symbol = myStopSymbol;
            _stopsGraphicsLayer.Renderer = myStopRenderer;

            // Add the start and end points GraphicsLayer to the LayerCollection in the Map. 
            MapView1.Map.Layers.Add(_stopsGraphicsLayer);

            // Call the asynchronous function to ensure all the layers have been loaded so that the user can interact with the Map.
            HandleLayersInitialized();

        }

        private async void HandleLayersInitialized()
        {
            try
            {
                // This next line of code is important. The Task.WhenAll is a Microsoft function that ascertains when a Task has 
                // completed. By using a LINQ query for MapView1.Map.Layers.Select we cycle through all of the Layers to know if we have 
                // a successful layer completion, an error or a cancel.
                await System.Threading.Tasks.Task.WhenAll(MapView1.Map.Layers.Select(layer => layer.InitializeAsync()).ToArray());

                // Once this next line of code executes, the IsMapReady will be called again and this time the _isMapReady global 
                // variable will be set to True and the PropertyChanged Event will be raised allowing the SolveRouteButton to be enabled.
                // This means that the user can now add stops on the map and the route will be calculated.
                IsMapReady = true;
            }
            catch (System.Exception ex)
            {
                // There was a problem, display it to the user.
                System.Windows.MessageBox.Show(ex.Message);
                return;
            }
        }

        private void SolveRouteButton_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            // The user clicked the SolveRouteButton. Call the CalculateRoute asynchronous function to add stops and solve the route.
            System.Threading.Tasks.Task myCalculateRouteTask = CalculateRoute();
        }

        private async System.Threading.Tasks.Task CalculateRoute()
        {
            // If the user clicked the SolveRouteButton more than once, clear out any existing stops and routes graphics.
            _routeGraphicsLayer.Graphics.Clear();
            _stopsGraphicsLayer.Graphics.Clear();

            try
            {

                // Mouse click 1: setting the start point for the route
                // ---------------------------------------------------

                // Get the Editor from the MapView.
                Esri.ArcGISRuntime.Controls.Editor myStartPointEditor = MapView1.Editor;

                // Get the MapPoint from where the user clicks in the Map Control. This will be the starting point for the route.
                Esri.ArcGISRuntime.Geometry.MapPoint myStartLocationMapPoint = await myStartPointEditor.RequestPointAsync();

                // Create a new Graphic and set it's geometry to the user clicked MapPoint
                Esri.ArcGISRuntime.Layers.Graphic myStartPointGraphic = new Esri.ArcGISRuntime.Layers.Graphic();
                myStartPointGraphic.Geometry = myStartLocationMapPoint;

                // Add the start point graphic to the stops GraphicsLayer.
                _stopsGraphicsLayer.Graphics.Add(myStartPointGraphic);

                // Update the TextBox in the GUI with the X/Y coordinate values of the start point.
                StartLocationText = " X: " + System.Math.Round(myStartLocationMapPoint.X, 0).ToString() + " Y: " + System.Math.Round(myStartLocationMapPoint.Y, 0).ToString();

                // Mouse click 2: setting the end point for the route
                // ---------------------------------------------------

                // Get the Editor from the MapView.
                Esri.ArcGISRuntime.Controls.Editor myEndPointEditor = MapView1.Editor;

                // Get the MapPoint from where the user clicks in the Map Control. This will be the ending point for the route.
                Esri.ArcGISRuntime.Geometry.MapPoint myEndLocationMapPoint = await myStartPointEditor.RequestPointAsync();

                // Create a new Graphic and set it's geometry to the user clicked MapPoint
                Esri.ArcGISRuntime.Layers.Graphic myEndPointGraphic = new Esri.ArcGISRuntime.Layers.Graphic();
                myEndPointGraphic.Geometry = myEndLocationMapPoint;

                // Add the start point graphic to the stops GraphicsLayer.
                _stopsGraphicsLayer.Graphics.Add(myEndPointGraphic);

                // Update the TextBox in the GUI with the X/Y coordinate values of the end point.
                EndLocationText = " X: " + System.Math.Round(myEndLocationMapPoint.X, 0).ToString() + " Y: " + System.Math.Round(myEndLocationMapPoint.Y, 0).ToString();

                // Set the arguments for the RouteTask:
                // ------------------------------------

                // Get the RouteParameters from the RouteTask.
                Esri.ArcGISRuntime.Tasks.NetworkAnalyst.RouteParameters myRouteParameters = await _routeTask.GetDefaultParametersAsync();

                // Define the settings for the RouteParameters. This includes setting the SpatialReference, ReturnDirections, DirectionsLengthUnit
                // and Stops. There are more even options that could be set but not demonstrated in this sample.
                myRouteParameters.OutSpatialReference = MapView1.SpatialReference;
                myRouteParameters.ReturnDirections = false;
                myRouteParameters.DirectionsLengthUnit = Esri.ArcGISRuntime.Geometry.LinearUnits.Kilometers;

                // Define a List of Graphics based upon the user start and end clicks in the Map Control that will serve as input
                // parameters for the RouteTask operation.
                System.Collections.Generic.List<Esri.ArcGISRuntime.Layers.Graphic> graphicsStops = new System.Collections.Generic.List<Esri.ArcGISRuntime.Layers.Graphic>();
                graphicsStops.Add(new Esri.ArcGISRuntime.Layers.Graphic(myStartLocationMapPoint));
                graphicsStops.Add(new Esri.ArcGISRuntime.Layers.Graphic(myEndLocationMapPoint));

                // Set the stops for the Route.
                myRouteParameters.SetStops(graphicsStops);

                // Call the asynchronous function to solve the RouteTask.
                Esri.ArcGISRuntime.Tasks.NetworkAnalyst.RouteResult routeResult = await _routeTask.SolveAsync(myRouteParameters);

                // Ensure we got at least one route back.
                if (routeResult.Routes.Count > 0)
                {

                    // Get the first Route from the List of Routes
                    Esri.ArcGISRuntime.Tasks.NetworkAnalyst.Route myFirstRoute = routeResult.Routes[0];

                    // Get the Geometry from the Graphic in the first Route.
                    Esri.ArcGISRuntime.Geometry.Geometry myRouteGeometry = myFirstRoute.RouteFeature.Geometry;

                    // Create a new Graphic based upon the Graphic.
                    Esri.ArcGISRuntime.Layers.Graphic myRouteGraphic = new Esri.ArcGISRuntime.Layers.Graphic(myRouteGeometry);

                    // Add the Graphic (a polyline) to the route GraphicsLayer. 
                    _routeGraphicsLayer.Graphics.Add(myRouteGraphic);

                }

            }
            catch (System.AggregateException ex)
            {
                // There was a problem, display the results to the user.
                var innermostExceptions = ex.Flatten().InnerExceptions;
                if (innermostExceptions != null && innermostExceptions.Count > 0)
                    System.Windows.MessageBox.Show(innermostExceptions[0].Message);
                else
                    System.Windows.MessageBox.Show(ex.Message);
            }
            catch (System.Exception ex)
            {
                // There was a problem, display the results to the user.
                System.Windows.MessageBox.Show("Error: " + ex.Message);
            }
            finally
            {
            }

        }


    }
}