Routing

Download Samples Repository

Description

This sample demonstrates offline routing with a network analyst LocalRouteTask.

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

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.OfflineRouting"
             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="layoutGrid">
        <Grid.Resources>
            <esri:SimpleMarkerSymbol x:Key="stopSymbol" Color="Green" Size="10" Style="Circle" />
            <esri:SimpleRenderer x:Key="stopsRenderer" Symbol="{StaticResource stopSymbol}" />

            <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="-13044000, 3855000, -13040000, 3858000, 3857">
				<esri:ArcGISTiledMapServiceLayer
                    ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
			</esri:Map>
			<esri:MapView.GraphicsOverlays>
				<esri:GraphicsOverlay ID="stopsOverlay" Renderer="{StaticResource stopsRenderer}" />
				<esri:GraphicsOverlay ID="routesOverlay" Renderer="{StaticResource routesRenderer}" />
				<esri:GraphicsOverlay ID="directionsOverlay" Renderer="{StaticResource directionsRenderer}" />
			</esri:MapView.GraphicsOverlays>
        </esri:MapView>

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

                <TextBlock Text="Click one or more stop locations on the map then double click 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" 
							  ItemsSource="{Binding ElementName=MyMapView, Path=GraphicsOverlays[directionsOverlay].Graphics}"
							  SelectedIndex="0">
                        <ListView.ItemContainerStyle>
                            <Style TargetType="ListViewItem">
                                <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
                                <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
                            </Style>
                        </ListView.ItemContainerStyle>

                        <ListView.View>
                            <GridView>
                                <GridViewColumn Header="Direction" DisplayMemberBinding="{Binding Attributes[Direction].Text}" Width="200" />
                                <GridViewColumn Header="Time" DisplayMemberBinding="{Binding Attributes[Direction].Time, StringFormat={}{0:h\\:mm\\:ss}}" Width="Auto" />
                                <GridViewColumn Header="Length" DisplayMemberBinding="{Binding Attributes[Length], StringFormat={}{0:0.00}}" Width="Auto" />
                            </GridView>
                        </ListView.View>
                    </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.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace ArcGISRuntime.Samples.Desktop
{
    /// <summary>
    /// This sample demonstrates offline routing with a network analyst LocalRouteTask.
    /// </summary>
    /// <title>Routing</title>
    /// <category>Offline</category>
    public partial class OfflineRouting : UserControl
    {
        private const string _localRoutingDatabase = @"..\..\..\samples-data\networks\san-diego\san-diego-network.geodatabase";
        private const string _networkName = "Streets_ND";

        private LocalRouteTask _routeTask;
        private Symbol _directionPointSymbol;
		private GraphicsOverlay _stopsOverlay;
		private GraphicsOverlay _routesOverlay;
		private GraphicsOverlay _directionsOverlay;
        private bool _isMapReady;

        public OfflineRouting()
        {
            InitializeComponent();

            _isMapReady = false;
            _directionPointSymbol = layoutGrid.Resources["directionPointSymbol"] as Symbol;
			_stopsOverlay = MyMapView.GraphicsOverlays["stopsOverlay"];
			_routesOverlay = MyMapView.GraphicsOverlays["routesOverlay"];
			_directionsOverlay = MyMapView.GraphicsOverlays["directionsOverlay"];

            MyMapView.ExtentChanged += MyMapView_ExtentChanged;
        }

        // Make sure the map is ready for user interaction
        private async void MyMapView_ExtentChanged(object sender, EventArgs e)
        {
            try
            {
                MyMapView.ExtentChanged -= MyMapView_ExtentChanged;

                await MyMapView.LayersLoadedAsync();
                _isMapReady = true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
            }
        }

        // Get user Stop points
        private void MyMapView_MapViewTapped(object sender, MapViewInputEventArgs e)
        {
            if (!_isMapReady)
                return;

            try
            {
                e.Handled = true;

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

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

				_stopsOverlay.Graphics.Add(new Graphic(e.Location));
            }
            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 (!_isMapReady || _stopsOverlay.Graphics.Count() < 2)
                return;

            try
            {
                e.Handled = true;

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

                if (_routeTask == null)
                    _routeTask = await Task.Run<LocalRouteTask>(() => new LocalRouteTask(_localRoutingDatabase, _networkName));

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

                var routeResult = await _routeTask.SolveAsync(routeParams);
                if (routeResult == null || routeResult.Routes == null || routeResult.Routes.Count() == 0)
                    throw new ApplicationException("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));

                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);

                await MyMapView.SetViewAsync(route.RouteFeature.Geometry.Extent.Expand(1.2));
            }
            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 GraphicFromRouteDirection(RouteDirection rd)
        {
            var graphic = new Graphic(rd.Geometry);
            graphic.Attributes.Add("Direction", rd);
            graphic.Attributes["Length"] = rd.GetLength(LinearUnits.Miles);
            if (rd.Geometry is MapPoint)
                graphic.Symbol = _directionPointSymbol;

            return graphic;
        }
    }
}
Feedback on this topic?