Routing with Directions

Download Samples Repository

Description

Demonstrates retrieving a route and driving directions between input locations with OnlineLocatorTask.

"Desktop" "Store" "Phone" Available for Desktop, Store, Phone

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.RoutingWithDirections"
             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">
    <Grid x:Name="LayoutRoot">
        <Grid.Resources>
            <esri:SimpleLineSymbol x:Key="routeSymbol" Color="Blue" Width="2" Style="Dot" />
            <esri:SimpleRenderer x:Key="routesRenderer" Symbol="{StaticResource routeSymbol}" />

            <esri:SimpleMarkerSymbol x:Key="directionPointSymbol" Color="Blue" Size="6" Style="X" />
            <esri:SimpleLineSymbol x:Key="directionLineSymbol" Color="Transparent" Width="2" Style="Solid" />
            <esri:SimpleRenderer x:Key="directionsRenderer" Symbol="{StaticResource directionLineSymbol}" />
        </Grid.Resources>
        
        <esri:MapView x:Name="MyMapView" 
					  MapViewTapped="MyMapView_MapViewTapped" 
					  MapViewDoubleTapped="MyMapView_MapViewDoubleTapped">
			<esri:Map InitialViewpoint="-117.24377026205757,32.61710761167467,-116.95879261773452,32.841266856294624,4326">
				<esri:ArcGISTiledMapServiceLayer
                    ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
			</esri:Map>
			<esri:MapView.GraphicsOverlays>
				<esri:GraphicsOverlay ID="RoutesOverlay" Renderer="{StaticResource routesRenderer}"/>
				<esri:GraphicsOverlay ID="StopsOverlay" />
				<esri:GraphicsOverlay ID="DirectionsOverlay" Renderer="{StaticResource directionsRenderer}" SelectionColor="#CCFF0000"/>
			</esri:MapView.GraphicsOverlays>
        </esri:MapView>

		<Border Background="White" BorderBrush="Black" BorderThickness="1"
				HorizontalAlignment="Right" VerticalAlignment="Top"
				Margin="30" Padding="20" Width="300">
			<Border.Effect>
				<DropShadowEffect/>
			</Border.Effect>
			<Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>

                <TextBlock Text="Tap one or more stop locations on the map then double tap the final stop to calculate a simple route with directions." 
                           TextWrapping="Wrap"/>

                <ProgressBar x:Name="progress" Grid.Row="1" IsIndeterminate="True" Visibility="Collapsed" Margin="0,12,0,0" />

                <Grid x:Name="panelResults" Grid.Row="2" Margin="0,12,0,0" Visibility="Collapsed">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>

                    <TextBlock Text="Route Details:"  FontSize="16" FontWeight="Bold" />
                    <TextBlock x:Name="txtRouteTotals" Grid.Row="1" FontStyle="Italic" />

                    <ListView x:Name="listDirections" Grid.Row="2"
                              SelectionMode="Single" SelectionChanged="listDirections_SelectionChanged">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Margin="4,0">
                                    <TextBlock Text="{Binding Attributes[Direction]}" FontSize="13" FontWeight="Bold" />
                                    <TextBlock Margin="8,0,0,0" FontSize="12" FontStyle="Italic">
                                        <Run Text="{Binding Attributes[Length]}" />
                                        <Run Text=" mi  /  " />
                                        <Run Text="{Binding Attributes[Time]}" />
                                    </TextBlock>
                                </StackPanel>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </Grid>
            </Grid>
        </Border>
    </Grid>
</UserControl>
using Esri.ArcGISRuntime.Controls;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Layers;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.Tasks.NetworkAnalyst;
using System;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ArcGISRuntime.Samples.Desktop
{
    /// <summary>
    /// Demonstrates retrieving a route and driving directions between input locations with OnlineLocatorTask.
    /// </summary>
    /// <title>Routing with Directions</title>
    /// <category>Tasks</category>
    /// <subcategory>Network Analyst</subcategory>
    public partial class RoutingWithDirections : UserControl
    {
		private const string OnlineRoutingService = "http://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/Route";

        private OnlineRouteTask _routeTask;
        private Symbol _directionPointSymbol;
        private GraphicsOverlay _stopsOverlay;
		private GraphicsOverlay _routesOverlay;
		private GraphicsOverlay _directionsOverlay;

        public RoutingWithDirections()
        {
            InitializeComponent();

			_directionPointSymbol = LayoutRoot.Resources["directionPointSymbol"] as Symbol;

			_stopsOverlay = MyMapView.GraphicsOverlays["StopsOverlay"];
			_routesOverlay = MyMapView.GraphicsOverlays["RoutesOverlay"];
			_directionsOverlay = MyMapView.GraphicsOverlays["DirectionsOverlay"];

            _routeTask = new OnlineRouteTask(new Uri(OnlineRoutingService));
        }

        // Get user Stop points
        private void MyMapView_MapViewTapped(object sender, MapViewInputEventArgs e)
        {
            try
            {
                e.Handled = true;

                if (_directionsOverlay.Graphics.Count() > 0)
                {
                    panelResults.Visibility = Visibility.Collapsed;

                    _stopsOverlay.Graphics.Clear();
                    _routesOverlay.Graphics.Clear();
                    _directionsOverlay.GraphicsSource = null;
                }

                var graphicIdx = _stopsOverlay.Graphics.Count + 1;
                _stopsOverlay.Graphics.Add(CreateStopGraphic(e.Location, graphicIdx));
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message, "Sample Error");
            }
        }

        // Calculate the route
        private async void MyMapView_MapViewDoubleTapped(object sender, Esri.ArcGISRuntime.Controls.MapViewInputEventArgs e)
        {
            if (_stopsOverlay.Graphics.Count() < 2)
                return;

            try
            {
                e.Handled = true;

                panelResults.Visibility = Visibility.Collapsed;
                progress.Visibility = Visibility.Visible;

                RouteParameters routeParams = await _routeTask.GetDefaultParametersAsync();
                routeParams.OutSpatialReference = MyMapView.SpatialReference;
                routeParams.ReturnDirections = true;
                routeParams.DirectionsLengthUnit = LinearUnits.Miles;
				routeParams.DirectionsLanguage = new CultureInfo("en-Us"); // CultureInfo.CurrentCulture;
                routeParams.SetStops(_stopsOverlay.Graphics);

                var routeResult = await _routeTask.SolveAsync(routeParams);
                if (routeResult == null || routeResult.Routes == null || routeResult.Routes.Count() == 0)
                    throw new Exception("No route could be calculated");

                var route = routeResult.Routes.First();
                _routesOverlay.Graphics.Add(new Graphic(route.RouteFeature.Geometry));

                _directionsOverlay.GraphicsSource = route.RouteDirections.Select(rd => GraphicFromRouteDirection(rd));
				listDirections.ItemsSource = _directionsOverlay.Graphics;

                var totalTime = route.RouteDirections.Select(rd => rd.Time).Aggregate(TimeSpan.Zero, (p, v) => p.Add(v));
                var totalLength = route.RouteDirections.Select(rd => rd.GetLength(LinearUnits.Miles)).Sum();
                txtRouteTotals.Text = string.Format("Time: {0:h':'mm':'ss} / Length: {1:0.00} mi", totalTime, totalLength);

				if (!route.RouteFeature.Geometry.IsEmpty)
					await MyMapView.SetViewAsync(route.RouteFeature.Geometry.Extent.Expand(1.25));
            }
            catch (AggregateException ex)
            {
                var innermostExceptions = ex.Flatten().InnerExceptions;
                if (innermostExceptions != null && innermostExceptions.Count > 0)
                {
                    MessageBox.Show(innermostExceptions[0].Message, "Sample Error");
                }
                else
                {
                    MessageBox.Show(ex.Message, "Sample Error");
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message, "Sample Error");
            }
            finally
            {
                progress.Visibility = Visibility.Collapsed;
                if (_directionsOverlay.Graphics.Count() > 0)
                    panelResults.Visibility = Visibility.Visible;
            }
        }

        private Graphic CreateStopGraphic(MapPoint location, int id)
        {
            var symbol = new CompositeSymbol();
            symbol.Symbols.Add(new SimpleMarkerSymbol() { Style = SimpleMarkerStyle.Circle, Color = Colors.Blue, Size = 16 });
            symbol.Symbols.Add(new TextSymbol()
            {
                Text = id.ToString(),
                Color = Colors.White,
                VerticalTextAlignment = VerticalTextAlignment.Middle,
                HorizontalTextAlignment = HorizontalTextAlignment.Center,
                YOffset = -1
            });

            var graphic = new Graphic()
            {
                Geometry = location,
                Symbol = symbol
            };

            return graphic;
        }

        private Graphic GraphicFromRouteDirection(RouteDirection rd)
        {
            var graphic = new Graphic(rd.Geometry);
            graphic.Attributes.Add("Direction", rd.Text);
            graphic.Attributes.Add("Time", string.Format("{0:h\\:mm\\:ss}", rd.Time));
            graphic.Attributes.Add("Length", string.Format("{0:0.00}", rd.GetLength(LinearUnits.Miles)));
            if (rd.Geometry is MapPoint)
                graphic.Symbol = _directionPointSymbol;

            return graphic;
        }

        private void listDirections_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _directionsOverlay.ClearSelection();

            if (e.AddedItems != null && e.AddedItems.Count == 1)
            {
                var graphic = e.AddedItems[0] as Graphic;
                graphic.IsSelected = true;
            }
        }
    }
}
Feedback on this topic?