Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for .NET

Location Display

Download Samples Repository

Description

This sample demonstrates the location display using the MapView.LocationDisplay attribute to show your location on a map.The user may change Location Provider settings and view basic details about the current location.

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

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.LocationDisplay"
             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>
        <esri:MapView x:Name="MyMapView" WrapAround="True">
            <esri:Map>
                <esri:ArcGISTiledMapServiceLayer
                    ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
            </esri:Map>
        </esri:MapView>

        <Border Background="White" BorderBrush="Black" BorderThickness="1"
				HorizontalAlignment="Left" VerticalAlignment="Top"
				Margin="30" Padding="20">
            <Border.Effect>
                <DropShadowEffect/>
            </Border.Effect>
            <StackPanel>
                <TextBlock Text="Location Display Settings" FontWeight="Bold" Margin="0,4"/>
                <CheckBox Content="Enabled" IsChecked="{Binding ElementName=MyMapView, Path=LocationDisplay.IsEnabled}" Margin="0,0,0,5"/>
                <TextBlock Text="Auto Pan Mode"/>
                <ComboBox SelectedItem="{Binding LocationDisplay.AutoPanMode, ElementName=MyMapView}" Margin="0,2,0,5">
                    <esri:AutoPanMode>Off</esri:AutoPanMode>
                    <esri:AutoPanMode>Default</esri:AutoPanMode>
                    <esri:AutoPanMode>Navigation</esri:AutoPanMode>
                </ComboBox>
                <TextBlock Text="Location Provider" />
                <ComboBox x:Name="providerSelector" SelectionChanged="providerSelector_SelectionChanged" Margin="0,2">
                    <ComboBoxItem IsSelected="True" Content="System Provider"/>
                    <ComboBoxItem Content="Random Simulator"/>
                </ComboBox>
                <Button x:Name="resetDisplay" Click="resetDisplay_Click" Margin="0,15,0,0" Height="22">
                    <TextBlock Text="Reset Map" Margin="3,0,0,0" Width="135"   />
                </Button>
            </StackPanel>
        </Border>

        <Border Background="White" BorderBrush="Black" BorderThickness="1"
				HorizontalAlignment="Right" VerticalAlignment="Top"
				Margin="0,30,30,0" Padding="20" Height="130" Width="136">
            <Border.Effect>
                <DropShadowEffect/>
            </Border.Effect>
        </Border>

        <Border Background="White" BorderBrush="Black" BorderThickness="1"
				HorizontalAlignment="Right" VerticalAlignment="Top"
				Margin="30" Padding="20">
            <StackPanel >
                <TextBlock Text="Current Location" FontWeight="Bold" Margin="0,4"/>
                <StackPanel>
                    <TextBlock Text="{Binding ElementName=MyMapView, Path=LocationDisplay.CurrentLocation.Location.X, StringFormat='X: {0:0.000000}'}" />
                    <TextBlock Text="{Binding ElementName=MyMapView, Path=LocationDisplay.CurrentLocation.Location.Y, StringFormat='Y: {0:0.000000}'}" />
                    <TextBlock Text="{Binding ElementName=MyMapView, Path=LocationDisplay.CurrentLocation.Course, StringFormat='Course: {0:0.000}'}" />
                    <TextBlock Text="{Binding ElementName=MyMapView, Path=LocationDisplay.CurrentLocation.Speed, StringFormat='Speed: {0:0.000}'}" />
                </StackPanel>
            </StackPanel>
        </Border>
    </Grid>
</UserControl>
using Esri.ArcGISRuntime.Controls;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Location;
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace ArcGISRuntime.Samples.Desktop
{
    /// <summary>
    /// This sample demonstrates the location display using the MapView.LocationDisplay attribute to show your location on a map.  The user may change Location Provider settings and view basic details about the current location.
    /// </summary>
    /// <title>Location Display</title>
    /// <category>Mapping</category>
    public partial class LocationDisplay : UserControl
    {
        /// <summary>Construct Location Display sample user control</summary>
        public LocationDisplay()
        {
            InitializeComponent();
        }

        private void providerSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (providerSelector.SelectedIndex == 0)
                MyMapView.LocationDisplay.LocationProvider = new SystemLocationProvider();
            else
                MyMapView.LocationDisplay.LocationProvider = new RandomProvider();
        }

        /// <summary>Reset the MapView by removing any map rotation and centering on the existing Location. </summary>
        private async void resetDisplay_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // If the LocationDisplay is enabled and a Location currently exists, reset the map
                // to zero rotation and center on the Location. Otherwise, set the MapView to center on 0,0.
                if (MyMapView.LocationDisplay != null &&
                    MyMapView.LocationDisplay.IsEnabled &&
                    MyMapView.LocationDisplay.CurrentLocation != null &&
                    MyMapView.LocationDisplay.CurrentLocation.Location.Extent != null)
                {
                    // Get the current AutoPanMode setting as it is automatically disabled when calling MyMapView.SetView().
                    var PanMode = MyMapView.LocationDisplay.AutoPanMode;

                    MyMapView.SetRotation(0);
                    await MyMapView.SetViewAsync(MyMapView.LocationDisplay.CurrentLocation.Location);

                    // Reset the AutoPanMode 
                    MyMapView.LocationDisplay.AutoPanMode = PanMode;
                }
                else
                {
                    var viewpoint = new Viewpoint(MyMapView.Map.Layers[0].FullExtent) { Rotation = 0.0 };
                    await MyMapView.SetViewAsync(viewpoint);
                }
            }
            catch (Exception ex)
            {
                 MessageBox.Show(ex.Message, "Sample Error");
            }
        }
    }

    /// <summary>Location provider that provides pseudo random location updates</summary>
    public class RandomProvider : ILocationProvider
    {
        private static Random randomizer = new Random();
        private DispatcherTimer timer;
        LocationInfo oldPosition;

        /// <summary>Construct random provider</summary>
        public RandomProvider()
        {
            timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
            timer.Tick += timer_Tick;
            // Default start location
            StartLatitude = 34.057104;
            StartLongitude = -117.196816;
        }

        // Called when the position timer triggers, and calculates the next position based on current speed and heading,
        // and adds a little randomization to current heading, speed, and accuracy.       
        private void timer_Tick(object sender, object e)
        {
            if (oldPosition == null)
            {
                oldPosition = new LocationInfo()
                {
                    Location = new MapPoint(StartLongitude, StartLatitude, new SpatialReference(4326)),
                    Speed = 0,
                    Course = 0,
                    HorizontalAccuracy = 20,
                };
            }
            var now = DateTime.Now;
            TimeSpan timeParsed = timer.Interval;
            double acceleration = randomizer.NextDouble() * 5 - 2.5;
            double deltaSpeed = acceleration * timeParsed.TotalSeconds;
            double newSpeed = Math.Max(0, deltaSpeed + oldPosition.Speed);
            double deltaCourse = randomizer.NextDouble() * 30 - 15;
            double newCourse = deltaCourse + oldPosition.Course;
            while (newCourse < 0) newCourse += 360;
            while (newCourse >= 360) newCourse -= 360;
            double distanceTravelled = (newSpeed + oldPosition.Speed) * .5 * timeParsed.TotalSeconds;
            double accuracy = Math.Min(500, Math.Max(20, oldPosition.HorizontalAccuracy + (randomizer.NextDouble() * 100 - 50)));
            var pos = GetPointFromHeadingGeodesic(new Point(oldPosition.Location.X, oldPosition.Location.Y), distanceTravelled, newCourse - 180);
            var newPosition = new LocationInfo()
            {
                Location = new MapPoint(pos.X, pos.Y, new SpatialReference(4326)),
                Speed = newSpeed,
                Course = newCourse,
                HorizontalAccuracy = accuracy,
            };
            oldPosition = newPosition;
            if (LocationChanged != null)
                LocationChanged(this, oldPosition);
        }

        // Gets a point on the globe based on a location, a heading and a distance.       
        private static Point GetPointFromHeadingGeodesic(Point start, double distance, double heading)
        {
            double brng = (180 + heading) / 180 * Math.PI;
            double lon1 = start.X / 180 * Math.PI;
            double lat1 = start.Y / 180 * Math.PI;
            double dR = distance / 6378137; //Angular distance in radians
            double lat2 = Math.Asin(Math.Sin(lat1) * Math.Cos(dR) + Math.Cos(lat1) * Math.Sin(dR) * Math.Cos(brng));
            double lon2 = lon1 + Math.Atan2(Math.Sin(brng) * Math.Sin(dR) * Math.Cos(lat1), Math.Cos(dR) - Math.Sin(lat1) * Math.Sin(lat2));
            double lon = lon2 / Math.PI * 180;
            double lat = lat2 / Math.PI * 180;
            while (lon < -180) lon += 360;
            while (lat < -90) lat += 180;
            while (lon > 180) lon -= 360;
            while (lat > 90) lat -= 180;
            return new Point(lon, lat);
        }

        /// <summary>Starting Latitude</summary>
        public double StartLatitude { get; set; }

        /// <summary>Starting Longitude</summary>
        public double StartLongitude { get; set; }

        /// <summary>Starts the location provider</summary>
        public Task StartAsync()
        {
            timer.Start();
            return Task.FromResult<bool>(true);
        }

        /// <summary>Stops the location provider</summary>
        public Task StopAsync()
        {
            timer.Stop();
            return Task.FromResult<bool>(true);
        }

        /// <summary>LocationChanged event (from ILocationProvider)</summary>
        public event EventHandler<LocationInfo> LocationChanged;
    }
}
Feedback on this topic?