User Tools

Site Tools


source_code_silverlighteditionsample_vehicletracking_cs.zip

Source Code SilverlightEditionSample VehicleTracking CS.zip

MainPage.xaml

 <UserControl x:Class="ThinkGeo.MapSuite.VehicleTracking.MainPage"  
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
     xmlns:local="clr-namespace:ThinkGeo.MapSuite.VehicleTracking"  
     xmlns:silverlight="clr-namespace:ThinkGeo.MapSuite.SilverlightEdition;assembly=SilverlightEdition"  
     mc:Ignorable="d" Width="Auto" Height="Auto">  
     <UserControl.Resources>  
         <Style TargetType="ButtonBase">  
         </Style>  
     </UserControl.Resources>  
     <Grid Style="{StaticResource sampleBody}">  
         <Grid.RowDefinitions>  
             <RowDefinition Height="auto" />  
             <RowDefinition Height="*" />  
             <RowDefinition Height="auto" />  
         </Grid.RowDefinitions>  
         <local:Header Grid.Row="0"/>  
         <Grid Grid.Row="1" SizeChanged="Grid_SizeChanged">  
             <Grid.ColumnDefinitions>  
                 <ColumnDefinition Width="auto" />  
                 <ColumnDefinition Width="*" />  
             </Grid.ColumnDefinitions>  
             <Grid Margin="5 0 0 0">  
                 <Grid.ColumnDefinitions>  
                     <ColumnDefinition Width="*" />  
                     <ColumnDefinition Width="auto" />  
                     <ColumnDefinition Width="5" />  
                 </Grid.ColumnDefinitions>  
                 <Grid x:Name="statusPanel" Grid.Row="0" Grid.Column="0" Margin="0 0 5 10">  
                     <Grid.RowDefinitions>  
                         <RowDefinition Height="Auto" />  
                         <RowDefinition Height="Auto" />  
                         <RowDefinition Height="Auto" />  
                         <RowDefinition Height="Auto" />  
                         <RowDefinition Height="Auto" />  
                         <RowDefinition Height="Auto" />  
                         <RowDefinition Height="*" />  
                     </Grid.RowDefinitions>  
                     <TextBlock Grid.Row="0" Text="Click to refresh vehicles:" Style="{StaticResource h5}" Margin="0 5 0 5"/>  
                     <Border Grid.Row="1" Style="{StaticResource fileset}">  
                         <StackPanel>  
                             <StackPanel Orientation="Horizontal">  
                                 <ToggleButton x:Name="AutoRefreshToggleButton" Content="Image/AutoRefresh.png" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="AutoRefreshClick" ToolTipService.ToolTip="Auto Refresh" Template="{StaticResource newAutoRefreshTemplate}" Margin="{StaticResource normalMargin}"  />  
                                 <TextBlock Text="Auto Refresh: " Style="{StaticResource bodyText}" VerticalAlignment="Center"/>  
                                 <TextBlock x:Name="OnOffTextBlock" Text="Off" FontWeight="SemiBold" Foreground="Red" VerticalAlignment="Center"/>  
                             </StackPanel>  
                             <StackPanel Orientation="Horizontal" Margin="0 5 0 0">  
                                 <Button Content="Image/RefreshManually.png" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="RefreshClick" ToolTipService.ToolTip="Refresh" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" />  
                                 <TextBlock Text="Refresh Manually" Style="{StaticResource bodyText}" VerticalAlignment="Center" />  
                             </StackPanel>  
                         </StackPanel>  
                     </Border>  
 
                     <TextBlock Grid.Row="2" Text="Interact with the map using these tools:" Style="{StaticResource h5}" Margin="0 5 0 5"/>  
                     <Border  Grid.Row="3" Style="{StaticResource fileset}">  
                         <StackPanel Orientation="Horizontal">  
                             <RadioButton IsChecked="True" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave"  GroupName="Map" Content="Image/pan.png" Click="ControlMapClick" ToolTipService.ToolTip="Pan map" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" />  
                             <RadioButton GroupName="Map" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Content="Image/draw.png" ToolTipService.ToolTip="Draw fences" Click="DrawFenceClick" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" />  
                             <RadioButton GroupName="Map" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Content="Image/measure.png" ToolTipService.ToolTip="Measure distance" Click="MeasureDistanceClick" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource normalMargin}" />  
                         </StackPanel>  
                     </Border>  
                     <StackPanel Grid.Row="4" x:Name="editPanel" Orientation="Horizontal" Visibility="Collapsed" >  
                         <RadioButton x:Name="DrawNewFenceRadioButton" Content="Image/draw_polygon.png" IsChecked="True" GroupName="Edit" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="DrawNewFenceClick" ToolTipService.ToolTip="Track new fences" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}"/>  
                         <RadioButton x:Name="EditFenceRadioButton" Content="Image/edit_polygon.png" GroupName="Edit" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="EditFenceClick" ToolTipService.ToolTip="Edit the selected fence" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}"/>  
                         <Button Content="Image/Remove_Polygon.png" Click="DeleteFenceClick" ToolTipService.ToolTip="Delete" Template="{StaticResource imageButtonTemplate}" Margin="15 0 5 0" />  
                         <Button Content="Image/save.png" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="SaveFenceClick" ToolTipService.ToolTip="Save" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" />  
                         <Button Content="Image/clear.png" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="CancelEditClick" ToolTipService.ToolTip="Delete" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" />  
                     </StackPanel>  
                     <StackPanel Grid.Row="4" Orientation="Horizontal" x:Name="measurePanel" Visibility="Collapsed">  
                         <RadioButton x:Name="rbtnMeasureLine" GroupName="Measure" IsChecked="True" Content="Image/line.png" Click="MeasureLineClick" ToolTipService.ToolTip="Measure line" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}"/>  
                         <RadioButton x:Name="rbtnMeasurePolygon" GroupName="Measure" Content="Image/polygon.png" Click="MeasurePolygonClick" ToolTipService.ToolTip="Measure polygon" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}"/>  
                         <Button Content="Image/clear.png" Click="CancelMeasureClick" ToolTipService.ToolTip="Cancel" Template="{StaticResource imageButtonTemplate}" Margin="{StaticResource editButtonMargin}" />  
                         <TextBlock Text="Unit:" VerticalAlignment="Center" Margin="10 0 5 0" />  
                         <ComboBox ItemsSource="{Binding UnitSystems}" SelectedItem="{Binding SelectedUnitSystem,Mode=TwoWay}" Height="20" Width="78" VerticalAlignment="Center">  
                             <ComboBox.ItemTemplate>  
                                 <DataTemplate>  
                                     <TextBlock Text="{Binding .}" VerticalAlignment="Center" />  
                                 </DataTemplate>  
                             </ComboBox.ItemTemplate>  
                         </ComboBox>  
                     </StackPanel>  
                     <Border Grid.Row="5" Style="{StaticResource headerBanner}">  
                         <TextBlock Style="{StaticResource headerText2}" Text="Tracked Vehicles"></TextBlock>  
                     </Border>  
                     <Border Grid.Row="6" Style="{StaticResource fileset}" Width="300" >  
                         <ScrollViewer VerticalScrollBarVisibility="Auto">  
                             <ItemsControl ItemsSource="{Binding Vehicles}" >  
                                 <ItemsControl.ItemTemplate>  
                                     <DataTemplate>  
                                         <Grid Margin="0 0 0 10">  
                                             <Grid.ColumnDefinitions>  
                                                 <ColumnDefinition Width="40" />  
                                                 <ColumnDefinition Width="5" />  
                                                 <ColumnDefinition Width="*" />  
                                             </Grid.ColumnDefinitions>  
                                             <Button Content="{Binding IconUri}" MouseEnter="Control_MouseEnter" MouseLeave="Control_MouseLeave" Click="ZoomToVehicleClick" Template="{StaticResource imageButtonTemplate}" HorizontalAlignment="Center" VerticalAlignment="Top" />  
                                             <StackPanel Grid.Column="2">  
                                                 <HyperlinkButton Click="ZoomToVehicleClick" Foreground="Black" FontWeight="Bold" FontSize="12" >  
                                                     <TextBlock Text="{Binding OwnerName}" TextDecorations="Underline" />  
                                                 </HyperlinkButton>  
                                                 <StackPanel Orientation="Horizontal">  
                                                     <Image Stretch="None" Source="Image/ball_green.png" />  
                                                     <TextBlock Text="{Binding Status}" Style="{StaticResource bodyText}" Foreground="#339900" Margin="3 0 0 0" />  
                                                 </StackPanel>  
                                                 <Grid>  
                                                     <Grid.ColumnDefinitions>  
                                                         <ColumnDefinition Width="Auto" />  
                                                         <ColumnDefinition Width="5" />  
                                                         <ColumnDefinition Width="*" />  
                                                     </Grid.ColumnDefinitions>  
                                                     <Grid.RowDefinitions>  
                                                         <RowDefinition Height="Auto" />  
                                                         <RowDefinition Height="Auto" />  
                                                         <RowDefinition Height="Auto" />  
                                                     </Grid.RowDefinitions>  
                                                     <TextBlock Style="{StaticResource bodyText}" Text="Area:" />  
                                                     <TextBlock Style="{StaticResource bodyText}" Text="Speed:" Grid.Row="1" />  
                                                     <TextBlock Style="{StaticResource bodyText}" Text="Duration:" Grid.Row="2" />  
                                                     <TextBlock Style="{StaticResource bodyText}" Text="{Binding Area}" Grid.Column="2" />  
                                                     <TextBlock Style="{StaticResource bodyText}" Text="{Binding Speed}" Grid.Row="1" Grid.Column="2" />  
                                                     <TextBlock Style="{StaticResource bodyText}" Text="{Binding Duration}" Grid.Row="2" Grid.Column="2" />  
                                                 </Grid>  
                                             </StackPanel>  
                                         </Grid>  
                                     </DataTemplate>  
                                 </ItemsControl.ItemTemplate>  
                             </ItemsControl>  
                         </ScrollViewer>  
                     </Border>  
                 </Grid>  
                 <CheckBox x:Name="toggle" Template="{StaticResource collapseExpandTemplate}" Content="Image/collapse.png" Click="CollapsExpandClick" Grid.Column="1" Cursor="Hand" Background="Transparent"  BorderBrush="Transparent" />  
                 <Rectangle Grid.Column="2">  
                     <Rectangle.Fill>  
                         <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">  
                             <GradientStop Color="#5c707d" Offset="0"></GradientStop>  
                             <GradientStop Color="#305c707d" Offset="1"></GradientStop>  
                         </LinearGradientBrush>  
                     </Rectangle.Fill>  
                 </Rectangle>  
             </Grid>  
             <silverlight:Map Grid.Column="1" x:Name="map1" MouseMove="Map_MouseMove" HorizontalAlignment="Left" VerticalAlignment="Top" Click="WpfMap_MapClick" />  
             <local:OverlaySwitcher x:Name="overlaySwitcher" OverlayNames="{Binding OverlayNames}" DefaultOverlayName="{Binding DefaultOverlayName}" ExpandImageUri="/MapSuiteVehicleTracking;component/Image/switcher_minimize.png" CollapseImageUri="/MapSuiteVehicleTracking;component/Image/switcher_maxmize.png" OverlayChanged="OverlaySwitcher_OverlayChanged" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Top" Width="200" Height="Auto" />  
             <Grid Grid.Column="1" x:Name="_loading"  Visibility="Collapsed" Background="#30D6D6D6" >  
                 <local:LoadingImageUserControl />  
             </Grid>  
         </Grid>  
         <Border Grid.Row="2" BorderBrush="Gray" BorderThickness="0 1 0 0">  
             <Grid Height="31" Background="#e2e2e2">  
                 <Grid.ColumnDefinitions>  
                     <ColumnDefinition Width="*" />  
                     <ColumnDefinition Width="Auto" />  
                     <ColumnDefinition Width="5" />  
                     <ColumnDefinition Width="Auto" />  
                 </Grid.ColumnDefinitions>  
                 <TextBlock x:Name="LocationXTextBlock" Width="105" VerticalAlignment="Center" Grid.Column="1" />  
                 <TextBlock x:Name="LocationYTextBlock" Width="100" VerticalAlignment="Center" Grid.Column="3" />  
             </Grid>  
         </Border>  
         <!--<local:Bottom Grid.Row="2" Height="45" ></local:Bottom>-->  
     </Grid>  
 </UserControl>  
 
 

MainPage.xaml.cs

 using System;  
 using System.Collections.ObjectModel;  
 using System.Globalization;  
 using System.IO;  
 using System.IO.IsolatedStorage;  
 using System.Linq;  
 using System.Windows;  
 using System.Windows.Controls;  
 using System.Windows.Controls.Primitives;  
 using System.Windows.Input;  
 using System.Windows.Media;  
 using System.Windows.Media.Animation;  
 using System.Windows.Media.Effects;  
 using System.Windows.Threading;  
 using ThinkGeo.MapSuite.SilverlightCore;  
 using ThinkGeo.MapSuite.SilverlightEdition;  
 using ThinkGeo.MapSuite.VehicleTracking.ServiceReference;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     public partial class MainPage  
     {  
         private const string worldMapKitName = "World Map Kit Map";  
         private const string openStreetMapName = "Open Street Map";  
         private const string bingMapsKeyFileName = "BingMapsKey.key";  
         private const string bingMapsRoadMapName = "Bing Maps Road Map";  
         private const string bingMapsAerialMapName = "Bing Maps Aerial Map";  
         private static readonly DateTime applicationStartTime = DateTime.Now;  
         private static readonly DateTime adjustedStartTime = new DateTime(2009, 7, 10, 11, 31, 0);  
 
         private bool isFirst = true;  
         private Storyboard storyboard;  
         private DropShadowEffect dropShadowEffect;  
         private VehicleTrackingViewModel viewModel;  
         private DispatcherTimer autoRefreshDispatcherTimer;  
 
         public MainPage()  
         {  
             InitializeComponent();  
 
             dropShadowEffect = new DropShadowEffect();  
             dropShadowEffect.Opacity = 0.8;  
             dropShadowEffect.ShadowDepth = 2;  
             dropShadowEffect.Color = Color.FromArgb(255, 254, 111, 63);  
 
             viewModel = new VehicleTrackingViewModel();  
             viewModel.OverlayNames.Add(worldMapKitName);  
             viewModel.OverlayNames.Add(openStreetMapName);  
             viewModel.OverlayNames.Add(bingMapsRoadMapName);  
             viewModel.OverlayNames.Add(bingMapsAerialMapName);  
             DataContext = viewModel;  
 
             Application.Current.Host.Content.IsFullScreen = true;  
             autoRefreshDispatcherTimer = new DispatcherTimer();  
             autoRefreshDispatcherTimer.Interval = TimeSpan.FromMilliseconds(5000);  
             autoRefreshDispatcherTimer.Tick += (s, e) => UpdateSpatialFencesAndVehicles();  
 
             AutoRefreshToggleButton.IsChecked = true;  
             StartAutoRefresh(AutoRefreshToggleButton);  
         }  
 
         private void SetupBaseOverlays()  
         {  
             // Add the World Map Kit WMS layer.  It is a free demo set of data for the world accessable with WMS.  
             WorldMapKitWmsSilverlightOverlay worldMapKitWmsOverlay = new WorldMapKitWmsSilverlightOverlay();  
             worldMapKitWmsOverlay.Projection = WorldMapKitProjection.SphericalMercator;  
             map1.Overlays.Add(worldMapKitName, worldMapKitWmsOverlay);  
 
             // Initialize SpatialFenceLayer.  
             InMemoryFeatureLayer spatialFenceLayer = new InMemoryFeatureLayer();  
             spatialFenceLayer.Open();  
             spatialFenceLayer.Columns.Add(new FeatureSourceColumn("Restricted", "Charater", 10));  
             spatialFenceLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = new AreaStyle(new GeoPen(GeoColor.FromArgb(255, 204, 204, 204), 2), new GeoSolidBrush(GeoColor.FromArgb(112, 255, 0, 0)));  
             spatialFenceLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateSimpleTextStyle("Restricted", "Arial", 12, false, GeoColor.StandardColors.Black, GeoColor.StandardColors.White, 2);  
             spatialFenceLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;  
 
             // Initialize SpatialFenceOverlay.  
             LayerOverlay spatialFenceOverlay = new LayerOverlay();  
             spatialFenceOverlay.Name = "SpatialFenceOverlay";  
             spatialFenceOverlay.Layers.Add("SpatialFenceLayer", spatialFenceLayer);  
             LayerOverlay traceOverlay = new LayerOverlay();  
             traceOverlay.Name = "TraceOverlay";  
 
             map1.Overlays.Add("SpatialFenceOverlay", spatialFenceOverlay);  
             map1.Overlays.Add("TraceOverlay", traceOverlay);  
         }  
 
         private void UpdateSpatialFencesAndVehicles(bool needRefresh = true)  
         {  
             // Update the fences from database.  
             UpdateSpatialFences();  
 
             // Update the vehicle locations on the map.  
             UpdateVehicles();  
 
             if (needRefresh) map1.Refresh();  
         }  
 
         private void UpdateSpatialFences()  
         {  
             // Get the spatial fence overlay and layer and then clear them  
             LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"];  
             InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"];  
             spatialFenceLayer.InternalFeatures.Clear();  
 
             TrackingAccessPrividerSourceClient client = new TrackingAccessPrividerSourceClient();  
             client.GetSpatialFencesCompleted += (s, e) =>  
             {  
                 // Insert fences from database into fence layer  
                 if (e.Result != null)  
                 {  
                     foreach (string spatialFence in e.Result)  
                     {  
                         var array = spatialFence.Split('|');  
                         if (array.Length == 2)  
                         {  
                             Feature feature = new Feature(array[0], array[1]);  
                             feature.ColumnValues["Restricted"] = "Restricted";  
                             if (spatialFenceLayer.InternalFeatures.Contains(array[1]))  
                             {  
                                 spatialFenceLayer.InternalFeatures.Remove(array[1]);  
                             }  
                             spatialFenceLayer.InternalFeatures.Add(array[1], feature);  
                         }  
                     }  
                     spatialFenceOverlay.Refresh();  
                 }  
             };  
             client.GetSpatialFencesAsync();  
         }  
 
         // Here we update the vehicles from the database.  In this sample we create our data provider each time and  
         // when we are finsihed with it we dispose it.  This is very safe however you may get better performance  
         // if you were to cache this.  We wanted to sample to be clean and safe and it is up to your expertise to  
         // enhance it further  
         private void UpdateVehicles()  
         {  
             LayerOverlay traceOverlay = (LayerOverlay)map1.Overlays["TraceOverlay"];  
             TrackingAccessPrividerSourceClient client = new TrackingAccessPrividerSourceClient();  
             client.GetCurrentVehiclesCompleted += (s, e) =>  
             {  
                 // Loop through all the vehicle to add the history points  
                 if (e.Result != null && e.Result.All(v => !string.IsNullOrEmpty(v.Value.VehicleIconVirtualPath)))  
                 {  
                     foreach (int vehicleId in e.Result.Keys)  
                     {  
                         Vehicle currentVehicle = e.Result[vehicleId];  
                         VehicleViewModel tempVehicleViewModel = viewModel.Vehicles.FirstOrDefault(v => v.OwnerName == currentVehicle.VehicleName);  
                         if (tempVehicleViewModel == null)  
                         {  
                             tempVehicleViewModel = new VehicleViewModel(currentVehicle);  
                             Dispatcher.BeginInvoke(() => viewModel.Vehicles.Add(tempVehicleViewModel));  
                         }  
                         else  
                         {  
                             tempVehicleViewModel.Vehicle = currentVehicle;  
                             tempVehicleViewModel.Load();  
                         }  
 
                         bool isInSpatialFence = CheckIsInSpatialFence(currentVehicle);  
                         tempVehicleViewModel.Area = isInSpatialFence ? "In restricted area" : "Out of restricted area";  
                         InMemoryFeatureLayer currentVehicleLayer;  
 
                         // Initialize vehicle overlay if it's not initialized  
                         if (!traceOverlay.Layers.Contains(currentVehicle.VehicleName))  
                         {  
                             // Create an InMemoryMarkerOverlay for the vehicle to hold the points and current location  
                             currentVehicleLayer = new InMemoryFeatureLayer();  
                             currentVehicleLayer.Open();  
                             currentVehicleLayer.Name = currentVehicle.Id.ToString(CultureInfo.InvariantCulture);  
                             currentVehicleLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(GetValueStyle(currentVehicle.VehicleIconVirtualPath));  
                             currentVehicleLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;  
 
                             // Add all the required columns so we can populate later  
                             currentVehicleLayer.FeatureSource.Open();  
                             currentVehicleLayer.Columns.Add(new FeatureSourceColumn("IsCurrentPosition"));  
                             currentVehicleLayer.Columns.Add(new FeatureSourceColumn("Speed"));  
                             currentVehicleLayer.Columns.Add(new FeatureSourceColumn("DateTime"));  
                             currentVehicleLayer.Columns.Add(new FeatureSourceColumn("Longitude"));  
                             currentVehicleLayer.Columns.Add(new FeatureSourceColumn("Latitude"));  
                             currentVehicleLayer.Columns.Add(new FeatureSourceColumn("VehicleName"));  
                             currentVehicleLayer.Columns.Add(new FeatureSourceColumn("Duration"));  
                             Dispatcher.BeginInvoke(() =>  
                             {  
                                 lock (traceOverlay.Layers)  
                                 {  
                                     traceOverlay.Layers.Add(currentVehicle.VehicleName, currentVehicleLayer);  
                                     traceOverlay.Refresh();  
                                 }  
                             });  
                         }  
                         else  
                         {  
                             // Find the overlay in the map  
                             currentVehicleLayer = (InMemoryFeatureLayer)traceOverlay.Layers[currentVehicle.VehicleName];  
                         }  
 
                         // Clear old vehicle's old positions  
                         currentVehicleLayer.InternalFeatures.Clear();  
 
                         // Add the vheicle's bread crumbs  
                         foreach (Location historyLocation in currentVehicle.HistoryLocations.Take(6))  
                         {  
                             Feature breadcrumbFeature = new Feature(MapSuiteSampleHelper.GetLocationPointShape(historyLocation).GetWellKnownBinary(), currentVehicle.VehicleName + historyLocation.DateTime.ToString(CultureInfo.InvariantCulture));  
                             breadcrumbFeature.ColumnValues["DateTime"] = historyLocation.DateTime.ToString(CultureInfo.InvariantCulture);  
                             breadcrumbFeature.ColumnValues["IsCurrentPosition"] = "IsNotCurrentPosition";  
                             breadcrumbFeature.ColumnValues["Speed"] = historyLocation.Speed.ToString(CultureInfo.InvariantCulture);  
                             breadcrumbFeature.ColumnValues["Longitude"] = historyLocation.Longitude.ToString(CultureInfo.InvariantCulture);  
                             breadcrumbFeature.ColumnValues["Latitude"] = historyLocation.Latitude.ToString(CultureInfo.InvariantCulture);  
                             breadcrumbFeature.ColumnValues["VehicleName"] = currentVehicle.VehicleName;  
                             breadcrumbFeature.ColumnValues["Duration"] = MapSuiteSampleHelper.GetSpeedDuration(currentVehicle).ToString(CultureInfo.InvariantCulture);  
                             currentVehicleLayer.InternalFeatures.Add(breadcrumbFeature.Id, breadcrumbFeature);  
                         }  
 
                         // Add the vehicle's latest position  
                         Feature latestPositionFeature = new Feature(MapSuiteSampleHelper.GetLocationPointShape(currentVehicle.Location).GetWellKnownBinary(), currentVehicle.VehicleName);  
                         latestPositionFeature.ColumnValues["DateTime"] = currentVehicle.Location.DateTime.ToString(CultureInfo.InvariantCulture);  
                         latestPositionFeature.ColumnValues["IsCurrentPosition"] = "IsCurrentPosition";  
                         latestPositionFeature.ColumnValues["Speed"] = currentVehicle.Location.Speed.ToString(CultureInfo.InvariantCulture);  
                         latestPositionFeature.ColumnValues["Longitude"] = currentVehicle.Location.Longitude.ToString(CultureInfo.InvariantCulture);  
                         latestPositionFeature.ColumnValues["Latitude"] = currentVehicle.Location.Latitude.ToString(CultureInfo.InvariantCulture);  
                         latestPositionFeature.ColumnValues["VehicleName"] = currentVehicle.VehicleName;  
                         latestPositionFeature.ColumnValues["Duration"] = MapSuiteSampleHelper.GetSpeedDuration(currentVehicle).ToString(CultureInfo.InvariantCulture);  
                         currentVehicleLayer.InternalFeatures.Add(latestPositionFeature.Id, latestPositionFeature);  
                     }  
                     traceOverlay.Refresh();  
                 }  
             };  
             DateTime currentTime = GetAdjustedCurrentDateTime();  
             client.GetCurrentVehiclesAsync(currentTime);  
         }  
 
         private bool CheckIsInSpatialFence(Vehicle vehicle)  
         {  
             LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"];  
             InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"];  
 
             // Get the point shape and then check if it is within any of the sptail fences using the QueryTools  
             PointShape pointShape = new PointShape(vehicle.Location.Longitude, vehicle.Location.Latitude);  
             spatialFenceLayer.Open();  
             Collection<Feature> spatialFencesWithin = spatialFenceLayer.QueryTools.GetFeaturesContaining(pointShape, ReturningColumnsType.NoColumns);  
 
             bool isInSpatialFence = spatialFencesWithin.Count > 0;  
             return isInSpatialFence;  
         }  
 
         private static ValueStyle GetValueStyle(string vehicleIconVirtualPath)  
         {  
             GeoImage vehicleImage = GetGeoImage(new Uri("/MapSuiteVehicleTracking;component/Image/" + vehicleIconVirtualPath, UriKind.RelativeOrAbsolute));  
             GeoImage historyImage = GetGeoImage(new Uri("/MapSuiteVehicleTracking;component/Image/ball_green.png", UriKind.RelativeOrAbsolute));  
 
             ValueStyle iconValueStyle = new ValueStyle();  
             iconValueStyle.ColumnName = "IsCurrentPosition";  
             iconValueStyle.ValueItems.Add(new ValueItem("IsCurrentPosition", new PointStyle(vehicleImage) { XOffsetInPixel = -16, YOffsetInPixel = -16 }));  
             iconValueStyle.ValueItems.Add(new ValueItem("IsNotCurrentPosition", new PointStyle(historyImage)));  
 
             return iconValueStyle;  
         }  
 
         private static GeoImage GetGeoImage(Uri uri)  
         {  
             Stream stream = Application.GetResourceStream(uri).Stream;  
             stream.Seek(0, SeekOrigin.Begin);  
             GeoImage geoImage = new GeoImage();  
             geoImage.SourceStream = stream;  
             return geoImage;  
         }  
 
         private void AutoRefreshClick(object sender, RoutedEventArgs e)  
         {  
             ToggleButton autoRefreshToggleButton = (ToggleButton)sender;  
             StartAutoRefresh(autoRefreshToggleButton);  
         }  
 
         private void StartAutoRefresh(ToggleButton autoRefreshToggleButton)  
         {  
             if (autoRefreshToggleButton.IsChecked.GetValueOrDefault())  
             {  
                 autoRefreshDispatcherTimer.Start();  
                 OnOffTextBlock.Foreground = new SolidColorBrush(Colors.Black);  
                 OnOffTextBlock.Text = "On";  
 
                 if (storyboard == null)  
                 {  
                     RotateTransform rotateTransform = new RotateTransform();  
                     rotateTransform.CenterX = 14;  
                     rotateTransform.CenterY = 14;  
 
                     autoRefreshToggleButton.RenderTransform = rotateTransform;  
 
                     DoubleAnimation AscendingDoubleAnimation = new DoubleAnimation();  
                     AscendingDoubleAnimation.From = 0;  
                     AscendingDoubleAnimation.To = 360;  
                     AscendingDoubleAnimation.RepeatBehavior = RepeatBehavior.Forever;  
                     AscendingDoubleAnimation.Duration = TimeSpan.FromSeconds(1.5);  
                     storyboard = new Storyboard();  
                     storyboard.Children.Add(AscendingDoubleAnimation);  
                     Storyboard.SetTarget(AscendingDoubleAnimation, rotateTransform);  
                     Storyboard.SetTargetProperty(AscendingDoubleAnimation, new PropertyPath("Angle"));  
                 }  
                 storyboard.Begin();  
             }  
             else  
             {  
                 autoRefreshDispatcherTimer.Stop();  
                 OnOffTextBlock.Foreground = new SolidColorBrush(Colors.Red);  
                 OnOffTextBlock.Text = "Off";  
                 storyboard.Stop();  
             }  
         }  
 
         private void RefreshClick(object sender, RoutedEventArgs e)  
         {  
             UpdateSpatialFencesAndVehicles();  
         }  
 
         private void WpfMap_MapClick(object sender, MapClickEventArgs e)  
         {  
             RectangleShape rectangle = GetBufferedRectangle(e.WorldPointShape);  
             LayerOverlay traceOverlay = (LayerOverlay)map1.Overlays["TraceOverlay"];  
             map1.Popups.Clear();  
             lock (traceOverlay.Layers)  
             {  
                 foreach (Layer layer in traceOverlay.Layers)  
                 {  
                     InMemoryFeatureLayer vehicleLayer = (InMemoryFeatureLayer)layer;  
                     vehicleLayer.Open();  
                     if (vehicleLayer.GetBoundingBox().Intersects(rectangle))  
                     {  
                         var resultFeatures = vehicleLayer.QueryTools.GetFeaturesIntersecting(rectangle, ReturningColumnsType.AllColumns);  
                         if (resultFeatures.Count > 0)  
                         {  
                             ShowPopup(e.WorldPointShape, GetVehicleInfor(resultFeatures[0]));  
                             break;  
                         }  
                     }  
                 }  
             }  
         }  
 
         private void ShowPopup(PointShape pointShape, string popupContent)  
         {  
             GeoPopup popup = new GeoPopup(pointShape);  
             TextBlock textBlock = new TextBlock { Foreground = new SolidColorBrush(Colors.Black), Text = popupContent, Margin = new Thickness(5) };  
             popup.Content = textBlock;  
             popup.Width = textBlock.ActualWidth + 32;  
             popup.Height = textBlock.ActualHeight + 20;  
             map1.Popups.Add(popup);  
             map1.Refresh();  
         }  
 
         private RectangleShape GetBufferedRectangle(PointShape pointShape)  
         {  
             PointShape clickedPoint = pointShape;  
             double currentResolution = map1.CurrentScale / (39.3701 * 96);  
             double offset = currentResolution * 16;  
             RectangleShape rectangle = new RectangleShape(clickedPoint.X - offset, clickedPoint.Y + offset, clickedPoint.X + offset, clickedPoint.Y - offset);  
             return rectangle;  
         }  
 
         private static string GetVehicleInfor(Feature feature)  
         {  
             ProjNetProjection proj4 = new ProjNetProjection(4326, 900913);  
             proj4.Open();  
 
             string longitudeString = "--";  
             string latitudeString = "--";  
             double longitude = double.NaN;  
             double latitude = double.NaN;  
             if (double.TryParse(feature.ColumnValues["Longitude"], out longitude) &&  
                 double.TryParse(feature.ColumnValues["Latitude"], out latitude))  
             {  
                 PointShape pointShape = new PointShape(longitude, latitude);  
                 pointShape = (PointShape)proj4.ConvertToInternalProjection(pointShape);  
 
                 longitudeString = pointShape.X.ToString("N2", CultureInfo.InvariantCulture);  
                 latitudeString = pointShape.Y.ToString("N2", CultureInfo.InvariantCulture);  
             }  
 
             proj4.Close();  
 
             return string.Format(CultureInfo.InvariantCulture, "Name:{0}\r\nLongitude:{1}\r\nLatitude:{2}\r\nSpeed:{3}mph\r\nTime:{4}"  
                 , feature.ColumnValues["VehicleName"]  
                 , longitudeString  
                 , latitudeString  
                 , feature.ColumnValues["Speed"]  
                 , feature.ColumnValues["DateTime"]);  
         }  
 
         private void ControlMapClick(object sender, RoutedEventArgs e)  
         {  
             if (((RadioButton)sender).IsChecked.GetValueOrDefault())  
             {  
                 editPanel.Visibility = Visibility.Collapsed;  
                 measurePanel.Visibility = Visibility.Collapsed;  
                 map1.TrackOverlay.TrackMode = TrackMode.None;  
             }  
         }  
 
         private void DrawFenceClick(object sender, RoutedEventArgs e)  
         {  
             if (((RadioButton)sender).IsChecked.GetValueOrDefault())  
             {  
                 map1.TrackOverlay.TrackEnded -= TrackOverlay_TrackEnded;  
                 map1.TrackOverlay.TrackMode = TrackMode.Polygon;  
                 editPanel.Visibility = Visibility.Visible;  
                 measurePanel.Visibility = Visibility.Collapsed;  
             }  
         }  
 
         private void MeasureLineClick(object sender, RoutedEventArgs e)  
         {  
             map1.TrackOverlay.TrackMode = TrackMode.Line;  
         }  
 
         private void MeasurePolygonClick(object sender, RoutedEventArgs e)  
         {  
             map1.TrackOverlay.TrackMode = TrackMode.Polygon;  
         }  
 
         private void CancelMeasureClick(object sender, RoutedEventArgs e)  
         {  
             ClearMeasuresAndPopups();  
         }  
 
         private void ClearMeasuresAndPopups()  
         {  
             foreach (Feature measureFeature in map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Where(f => (string)f.Tag == "Measure").ToList())  
             {  
                 map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Remove(measureFeature);  
             }  
             map1.Popups.Clear();  
             map1.TrackOverlay.Refresh();  
         }  
 
         private void MeasureDistanceClick(object sender, RoutedEventArgs e)  
         {  
             if (((RadioButton)sender).IsChecked.GetValueOrDefault())  
             {  
                 map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick;  
                 if (map1.EditOverlay.EditShapesLayer.InternalFeatures.Count > 0)  
                 {  
                     SaveSpatialFences(() => UpdateSpatialFencesAndVehicles());  
                 }  
                 else if (map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count > 0)  
                 {  
                     CancelEdit();  
                 }  
                 editPanel.Visibility = Visibility.Collapsed;  
                 measurePanel.Visibility = Visibility.Visible;  
                 map1.TrackOverlay.TrackMode = rbtnMeasureLine.IsChecked.GetValueOrDefault() ? TrackMode.Line : TrackMode.Polygon;  
                 map1.TrackOverlay.TrackStarting -= TrackOverlay_TrackStarting;  
                 map1.TrackOverlay.TrackStarting += TrackOverlay_TrackStarting;  
                 map1.TrackOverlay.TrackEnded -= TrackOverlay_TrackEnded;  
                 map1.TrackOverlay.TrackEnded += TrackOverlay_TrackEnded;  
             }  
         }  
 
         private void TrackOverlay_TrackStarting(object sender, TrackStartingTrackInteractiveOverlayEventArgs e)  
         {  
             if (map1.TrackOverlay.TrackMode == TrackMode.Line || map1.TrackOverlay.TrackMode == TrackMode.Polygon)  
             {  
                 ClearMeasuresAndPopups();  
             }  
         }  
 
         private void TrackOverlay_TrackEnded(object sender, TrackEndedTrackInteractiveOverlayEventArgs e)  
         {  
             if (map1.TrackOverlay.TrackMode == TrackMode.Polygon)  
             {  
                 PolygonShape polygonShape = e.TrackShape as PolygonShape;  
                 if (polygonShape != null)  
                 {  
                     double area = -1;  
                     string areaUnit = "sqr.m.";  
                     if (viewModel.SelectedUnitSystem == UnitSystem.Metric)  
                     {  
                         areaUnit = "sqr.m.";  
                         area = polygonShape.GetArea(GeographyUnit.Meter, AreaUnit.SquareMeters);  
                     }  
                     else if (viewModel.SelectedUnitSystem == UnitSystem.Imperial)  
                     {  
                         areaUnit = "ac.";  
                         area = polygonShape.GetArea(GeographyUnit.Meter, AreaUnit.Acres);  
                     }  
                     if (area > 0)  
                     {  
                         ShowPopup(new PointShape(polygonShape.OuterRing.Vertices[polygonShape.OuterRing.Vertices.Count|- 1]), string.Format("Area: {0} {1}", area.ToString("N1"), areaUnit));  
                     }  
                     if (map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count > 0)  
                     {  
                         Feature lastFeature = map1.TrackOverlay.TrackShapeLayer.InternalFeatures.LastOrDefault();  
                         lastFeature.Tag = "Measure";  
                         map1.TrackOverlay.TrackShapeLayer.InternalFeatures.RemoveAt(map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count - 1);  
                         map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(lastFeature);  
                     }  
                 }  
             }  
 
             if (map1.TrackOverlay.TrackMode == TrackMode.Line)  
             {  
                 string unit = string.Empty;  
                 LineShape lineShape = e.TrackShape as LineShape;  
                 if (lineShape != null)  
                 {  
                     double lenth = 0;  
                     if (viewModel.SelectedUnitSystem == UnitSystem.Metric)  
                     {  
                         lenth = lineShape.GetLength(GeographyUnit.Meter, DistanceUnit.Meter);  
                         unit = "m";  
                         if (lenth >= 1000)  
                         {  
                             unit = "km";  
                             lenth = Math.Round(lenth / 1000d, 1);  
                         }  
                     }  
                     else if (viewModel.SelectedUnitSystem == UnitSystem.Imperial)  
                     {  
                         lenth = lineShape.GetLength(GeographyUnit.Meter, DistanceUnit.Feet);  
                         unit = "ft";  
                         if (lenth >= 5280)  
                         {  
                             unit = "mi";  
                             lenth = Math.Round(lenth / 5280d, 1);  
                         }  
                     }  
 
                     string lengthString = lenth.ToString("N1");  
                     ShowPopup(new PointShape(lineShape.Vertices[lineShape.Vertices.Count|- 1]), string.Format("Total Length: {0} {1}", lengthString, unit));  
 
                     if (map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count > 0)  
                     {  
                         var lastFeature = map1.TrackOverlay.TrackShapeLayer.InternalFeatures.LastOrDefault();  
                         lastFeature.Tag = "Measure";  
                         map1.TrackOverlay.TrackShapeLayer.InternalFeatures.RemoveAt(map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Count - 1);  
                         map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(lastFeature);  
                     }  
                 }  
             }  
         }  
 
         private void DrawNewFenceClick(object sender, RoutedEventArgs e)  
         {  
             DrawNewFence();  
         }  
 
         private void DrawNewFence()  
         {  
             CancelEdit();  
             map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick;  
             map1.TrackOverlay.TrackMode = TrackMode.Polygon;  
         }  
 
         private void DeleteFenceClick(object sender, RoutedEventArgs e)  
         {  
             if (map1.EditOverlay.EditShapesLayer.InternalFeatures.Count == 0)  
             {  
                 MessageBox.Show("Please choose a fence!", "Vehicle Tracking", MessageBoxButton.OK);  
             }  
             else if (map1.EditOverlay.EditShapesLayer.InternalFeatures.Count > 0)  
             {  
                 if (MessageBox.Show("Are you sure you want to delete the fence you have selected?", "Vehicle Tracking", MessageBoxButton.OKCancel) == MessageBoxResult.OK)  
                 {  
                     map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick;  
                     map1.EditOverlay.EditShapesLayer.InternalFeatures.Clear();  
                     LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"];  
                     ((InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"]).InternalFeatures.Clear();  
                     SaveSpatialFences(() => UpdateSpatialFencesAndVehicles());  
                 }  
             }  
         }  
 
         private void SaveFenceClick(object sender, RoutedEventArgs e)  
         {  
             map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick;  
             SaveSpatialFences(() => UpdateSpatialFencesAndVehicles());  
             if (EditFenceRadioButton.IsChecked.GetValueOrDefault())  
             {  
                 EditFenceRadioButton.IsChecked = false;  
                 DrawNewFenceRadioButton.IsChecked = true;  
                 DrawNewFence();  
             }  
         }  
 
         private void EditFenceClick(object sender, RoutedEventArgs e)  
         {  
             ClearMeasuresAndPopups();  
             map1.TrackOverlay.TrackMode = TrackMode.None;  
             LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"];  
             InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"];  
 
             // Move spatial fences from spatial fence layer to edit overlay for editing  
             foreach (Feature feature in spatialFenceLayer.InternalFeatures)  
             {  
                 if (!map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Contains(feature.Id))  
                 {  
                     map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(feature.Id, feature);  
                 }  
                 if (!spatialFenceLayer.FeatureIdsToExclude.Contains(feature.Id))  
                 {  
                     spatialFenceLayer.FeatureIdsToExclude.Add(feature.Id);  
                 }  
             }  
 
             map1.TrackOverlay.MapMouseClick -= TrackOverlay_MapMouseClick;  
             map1.TrackOverlay.MapMouseClick += TrackOverlay_MapMouseClick;  
 
             UpdateVehicles();  
             map1.Refresh();  
         }  
 
         private void TrackOverlay_MapMouseClick(object sender, MapMouseClickInteractiveOverlayEventArgs e)  
         {  
             PointShape clickedPoint = new PointShape(e.InteractionArguments.WorldX, e.InteractionArguments.WorldY);  
             RectangleShape rect = GetBufferedRectangle(clickedPoint);  
             if (!map1.TrackOverlay.TrackShapeLayer.IsOpen)  
             {  
                 map1.TrackOverlay.TrackShapeLayer.Open();  
             }  
             Collection<Feature> intersectingFeatures = map1.TrackOverlay.TrackShapeLayer.QueryTools.GetFeaturesIntersecting(rect, ReturningColumnsType.AllColumns);  
             if (intersectingFeatures.Count > 0)  
             {  
                 if (map1.EditOverlay.EditShapesLayer.InternalFeatures.Count > 0)  
                 {  
                     foreach (var item in map1.EditOverlay.EditShapesLayer.InternalFeatures)  
                     {  
                         map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Add(item);  
                     }  
                     map1.EditOverlay.EditShapesLayer.InternalFeatures.Clear();  
                 }  
 
                 map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Remove(intersectingFeatures[0].Id);  
                 map1.EditOverlay.EditShapesLayer.InternalFeatures.Add(intersectingFeatures[0]);  
                 map1.EditOverlay.CalculateAllControlPoints();  
                 map1.Refresh();  
             }  
         }  
 
         private void SaveSpatialFences(Action executeAction)  
         {  
             LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"];  
             InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"];  
             foreach (var item in spatialFenceLayer.FeatureIdsToExclude)  
             {  
                 if (spatialFenceLayer.InternalFeatures.Contains(item))  
                 {  
                     spatialFenceLayer.InternalFeatures.Remove(item);  
                 }  
             }  
             spatialFenceLayer.FeatureIdsToExclude.Clear();  
             // Save the new spatial fences from edit overlay into the spatial fence layer  
             foreach (Feature feature in map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Where(f => (string)f.Tag != "Measure"))  
             {  
                 if (!spatialFenceLayer.InternalFeatures.Contains(feature.Id))  
                 {  
                     spatialFenceLayer.InternalFeatures.Add(feature.Id, feature);  
                 }  
             }  
 
             foreach (Feature feature in map1.EditOverlay.EditShapesLayer.InternalFeatures)  
             {  
                 if (!spatialFenceLayer.InternalFeatures.Contains(feature.Id))  
                 {  
                     spatialFenceLayer.InternalFeatures.Add(feature.Id, feature);  
                 }  
             }  
             spatialFenceOverlay.Refresh();  
 
             TrackingAccessPrividerSourceClient client = new TrackingAccessPrividerSourceClient();  
             client.DeleteAndUpdateAndInsertSpatialFencesCompleted += (s, e) =>  
             {  
                 // Turn the track mode to none and clear the features in the edit overlay  
                 map1.TrackOverlay.TrackMode = TrackMode.None;  
                 map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear();  
                 map1.EditOverlay.EditShapesLayer.InternalFeatures.Clear();  
                 map1.Popups.Clear();  
                 map1.TrackOverlay.Refresh();  
                 map1.EditOverlay.CalculateAllControlPoints();  
                 map1.EditOverlay.Refresh();  
                 if (executeAction != null)  
                 {  
                     executeAction();  
                     if (EditFenceRadioButton.IsChecked.GetValueOrDefault() || DrawNewFenceRadioButton.IsChecked.GetValueOrDefault())  
                     {  
                         EditFenceRadioButton.IsChecked = false;  
                         DrawNewFenceRadioButton.IsChecked = true;  
                         DrawNewFence();  
                     }  
                 }  
             };  
 
             ObservableCollection<string> excludeFeatureWktIds = new ObservableCollection<string>(spatialFenceLayer.InternalFeatures.Select(f => f.GetWellKnownText() + "|" + f.Id).ToList());  
             client.DeleteAndUpdateAndInsertSpatialFencesAsync(excludeFeatureWktIds);  
         }  
 
         private void ZoomToVehicleClick(object sender, RoutedEventArgs e)  
         {  
             LayerOverlay traceOverlay = (LayerOverlay)map1.Overlays["TraceOverlay"];  
             FrameworkElement frameworkElement = (FrameworkElement)sender;  
             VehicleViewModel vehicleViewModel = frameworkElement.DataContext as VehicleViewModel;  
             if (vehicleViewModel != null)  
             {  
                 InMemoryFeatureLayer vehicleFeatureLayer = traceOverlay.Layers[vehicleViewModel.OwnerName] as InMemoryFeatureLayer;  
                 if (vehicleFeatureLayer != null)  
                 {  
                     PointShape centerPoint = vehicleFeatureLayer.InternalFeatures[vehicleFeatureLayer.InternalFeatures.Count|- 1].GetShape() as PointShape;  
                     map1.ZoomTo(centerPoint, 15);  
                 }  
             }  
         }  
 
         private void CollapsExpandClick(object sender, RoutedEventArgs e)  
         {  
             CheckBox CollapsExpandCheckBox = sender as CheckBox;  
             if (CollapsExpandCheckBox != null)  
             {  
                 if (CollapsExpandCheckBox.IsChecked.GetValueOrDefault())  
                 {  
                     CollapsExpandCheckBox.Content = new Uri("Image/expand.png", UriKind.RelativeOrAbsolute);  
                     statusPanel.Visibility = Visibility.Collapsed;  
                     Grid grid = map1.Parent as Grid;  
                     if (grid != null)  
                     {  
                         map1.Width = grid.ActualWidth;  
                     }  
                 }  
                 else  
                 {  
                     CollapsExpandCheckBox.Content = new Uri("Image/collapse.png", UriKind.RelativeOrAbsolute);  
                     statusPanel.Visibility = Visibility.Visible;  
                     Grid grid = map1.Parent as Grid;  
                     if (grid != null)  
                     {  
                         map1.Width = grid.ColumnDefinitions.Last().ActualWidth;  
                     }  
                 }  
             }  
         }  
 
         private void Control_MouseEnter(object sender, MouseEventArgs e)  
         {  
             Control control = sender as Control;  
             if (control != null)  
             {  
                 control.Effect = dropShadowEffect;  
             }  
         }  
 
         private void Control_MouseLeave(object sender, MouseEventArgs e)  
         {  
             Control control = sender as Control;  
             if (control != null)  
             {  
                 control.Effect = null;  
             }  
         }  
 
         private void CancelEditClick(object sender, RoutedEventArgs e)  
         {  
             CancelEdit();  
         }  
 
         private void CancelEdit()  
         {  
             map1.EditOverlay.EditShapesLayer.InternalFeatures.Clear();  
             foreach (var editFeature in map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Where(f => (string)f.Tag != "Measure").ToList())  
             {  
                 map1.TrackOverlay.TrackShapeLayer.InternalFeatures.Remove(editFeature);  
             }  
             LayerOverlay spatialFenceOverlay = (LayerOverlay)map1.Overlays["SpatialFenceOverlay"];  
             InMemoryFeatureLayer spatialFenceLayer = (InMemoryFeatureLayer)spatialFenceOverlay.Layers["SpatialFenceLayer"];  
             spatialFenceLayer.FeatureIdsToExclude.Clear();  
             map1.EditOverlay.Refresh();  
             map1.TrackOverlay.Refresh();  
             spatialFenceOverlay.Refresh();  
             if (EditFenceRadioButton.IsChecked.GetValueOrDefault())  
             {  
                 EditFenceRadioButton.IsChecked = false;  
                 DrawNewFenceRadioButton.IsChecked = true;  
                 DrawNewFence();  
             }  
         }  
 
         private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)  
         {  
             Grid grid = sender as Grid;  
             if (grid != null)  
             {  
                 map1.Width = grid.ColumnDefinitions[1].ActualWidth;  
                 map1.Height = grid.ActualHeight;  
                 if (isFirst)  
                 {  
                     isFirst = false;  
                     // Setup the map.  
                     map1.MapUnit = GeographyUnit.Meter;  
                     map1.MapTools.ScaleLine.IsEnabled = true;  
                     // Add the various overlays such as vehicles, fences etc.  
                     SetupBaseOverlays();  
 
                     UpdateSpatialFencesAndVehicles(false);  
                     map1.CurrentExtent = new RectangleShape(-10785099.4221547, 3916104.57324868, -10779357.0938025, 3912421.26612761);  
                 }  
             }  
         }  
 
         private void OverlaySwitcher_OverlayChanged(object sender, OverlayChangedOverlaySwitcherEventArgs e)  
         {  
             switch (e.NewCheckedOverlayName)  
             {  
                 case worldMapKitName:  
                     if (map1.Overlays.Contains(worldMapKitName)) map1.Overlays.Remove(worldMapKitName);  
                     map1.Overlays.Insert(0, worldMapKitName, new WorldMapKitWmsSilverlightOverlay { Projection = WorldMapKitProjection.SphericalMercator });  
                     if (map1.Overlays.Contains(openStreetMapName)) map1.Overlays.Remove(openStreetMapName);  
                     if (map1.Overlays.Contains(bingMapsRoadMapName)) map1.Overlays.Remove(bingMapsRoadMapName);  
                     map1.Refresh();  
                     break;  
                 case openStreetMapName:  
                     if (map1.Overlays.Contains(openStreetMapName)) map1.Overlays.Remove(openStreetMapName);  
                     map1.Overlays.Insert(0, openStreetMapName, new OpenStreetMapOverlay());  
                     if (map1.Overlays.Contains(worldMapKitName)) map1.Overlays.Remove(worldMapKitName);  
                     if (map1.Overlays.Contains(bingMapsRoadMapName)) map1.Overlays.Remove(bingMapsRoadMapName);  
                     map1.Refresh();  
                     break;  
                 case bingMapsRoadMapName:  
                 case bingMapsAerialMapName:  
                     bool needShowInputBingMapKeyWindow = true;  
                     if (IsolatedStorageSettings.ApplicationSettings.Contains(bingMapsKeyFileName))  
                     {  
                         string bingmapsKey = IsolatedStorageSettings.ApplicationSettings[bingMapsKeyFileName].ToString();  
                         if (!string.IsNullOrEmpty(bingmapsKey))  
                         {  
                             LoadBingMaps(e.NewCheckedOverlayName, bingmapsKey);  
                             needShowInputBingMapKeyWindow = false;  
                         }  
                     }  
                     if (needShowInputBingMapKeyWindow)  
                     {  
                         BingMapsApplicationIdPromptWindow bingMapsApplicationIdPromptWindow = new BingMapsApplicationIdPromptWindow();  
                         bingMapsApplicationIdPromptWindow.Closing += (s, args) =>  
                         {  
                             if (bingMapsApplicationIdPromptWindow.DialogResult.GetValueOrDefault())  
                             {  
                                 LoadBingMaps(e.NewCheckedOverlayName, bingMapsApplicationIdPromptWindow.ApplicationId);  
                                 IsolatedStorageSettings.ApplicationSettings.Add(bingMapsKeyFileName, bingMapsApplicationIdPromptWindow.ApplicationId);  
                             }  
                             else overlaySwitcher.BindingOverlayNames(e.OldCheckedOverlayName);  
                         };  
                         bingMapsApplicationIdPromptWindow.Show();  
                     }  
                     break;  
             }  
         }  
 
         private void LoadBingMaps(string newCheckedOverlayName, string bingMapsKey)  
         {  
             BingMapsStyle bingMapsStyle = newCheckedOverlayName == bingMapsRoadMapName ? BingMapsStyle.Roads : BingMapsStyle.Aerial;  
             if (map1.Overlays.Contains(bingMapsRoadMapName)) map1.Overlays.Remove(bingMapsRoadMapName);  
             map1.Overlays.Insert(0, bingMapsRoadMapName, new BingMapsOverlay(bingMapsRoadMapName, bingMapsKey, bingMapsStyle));  
             if (map1.Overlays.Contains(openStreetMapName)) map1.Overlays.Remove(openStreetMapName);  
             if (map1.Overlays.Contains(worldMapKitName)) map1.Overlays.Remove(worldMapKitName);  
             map1.Refresh();  
         }  
 
         private void Map_MouseMove(object sender, MouseEventArgs e)  
         {  
             Point screenPoint = e.GetPosition(map1);  
             PointShape worldPoint = ExtentHelper.ToWorldCoordinate(map1.CurrentExtent, screenPoint, map1.ActualWidth, map1.ActualHeight);  
             LocationXTextBlock.Text = string.Format("X:{0:#,0.##}", worldPoint.X);  
             LocationYTextBlock.Text = string.Format("Y:{0:#,0.##}", worldPoint.Y);  
         }  
 
         private static DateTime GetAdjustedCurrentDateTime()  
         {  
             // This vehicle tracking sample contains some simulated data  
             // This method stores the real time when the application started and reflects to the start sample time  
             // When the actual time increments 1 second, the sample time increments 6 seconds  
             //  
             // To make the application run in real time just have this method return to current date time  
             //  
             double realSpentTime = TimeSpan.FromTicks(DateTime.Now.Ticks - applicationStartTime.Ticks).TotalSeconds;  
             int sampleSpentTime = (int)(realSpentTime * 12);  
             DateTime currentSampleTime = adjustedStartTime.AddSeconds(sampleSpentTime);  
 
             return currentSampleTime;  
         }  
     }  
 }  
 
 

VehicleTrackingViewModel.cs

 using System.Collections.ObjectModel;  
 using System.Linq;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     public class VehicleTrackingViewModel : ViewModelBase  
     {  
         private string defaultOverlayName;  
         private UnitSystem selectedUnitSystem;  
         private Collection<string> overlayNames;  
         private Collection<UnitSystem> unitSystems;  
         private ObservableCollection<VehicleViewModel> vehicles;  
 
         public VehicleTrackingViewModel()  
         {  
             overlayNames = new Collection<string>();  
             vehicles = new ObservableCollection<VehicleViewModel>();  
             unitSystems = new Collection<UnitSystem> { UnitSystem.Imperial, UnitSystem.Metric };  
             selectedUnitSystem = unitSystems[0];  
         }  
 
         public ObservableCollection<VehicleViewModel> Vehicles  
         {  
             get { return vehicles; }  
         }  
 
         public Collection<UnitSystem> UnitSystems  
         {  
             get { return unitSystems; }  
         }  
 
         public UnitSystem SelectedUnitSystem  
         {  
             get { return selectedUnitSystem; }  
             set { selectedUnitSystem = value; }  
         }  
 
         public Collection<string> OverlayNames  
         {  
             get { return overlayNames; }  
         }  
 
         public string DefaultOverlayName  
         {  
             get { return string.IsNullOrEmpty(defaultOverlayName) ? overlayNames.FirstOrDefault() : defaultOverlayName; }  
             set { defaultOverlayName = value; }  
         }  
     }  
 
     public enum UnitSystem  
     {  
         Imperial = 0,  
         Metric = 1,  
     }  
 }  
 
 

TrackingDataProvider.cs

 using System.Globalization;  
 using ThinkGeo.MapSuite.VehicleTracking.ServiceReference;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     public class VehicleViewModel : ViewModelBase  
     {  
         private string area;  
         private string speed;  
         private string status;  
         private string iconUri;  
         private string duration;  
         private string ownerName;  
         private Vehicle vehicle;  
 
         public VehicleViewModel()  
             : this(null)  
         { }  
 
         public VehicleViewModel(Vehicle vehicle)  
         {  
             ownerName = vehicle.VehicleName;  
             iconUri = "Image/" + vehicle.VehicleIconVirtualPath;  
             Vehicle = vehicle;  
 
             Load();  
         }  
 
         public Vehicle Vehicle  
         {  
             get { return vehicle; }  
             set { vehicle = value; }  
         }  
 
         public void Load()  
         {  
             Status = MapSuiteSampleHelper.GetCurrentState(vehicle);  
             Speed = vehicle.Location.Speed.ToString(CultureInfo.InvariantCulture) + " mph";  
             Duration = MapSuiteSampleHelper.GetSpeedDuration(vehicle).ToString(CultureInfo.InvariantCulture) + " min";  
         }  
 
         public string Status  
         {  
             get { return status; }  
             set  
             {  
                 status = value;  
                 RaisePropertyChanged(() => Status);  
             }  
         }  
 
         public string IconUri  
         {  
             get { return iconUri; }  
             set  
             {  
                 iconUri = value;  
                 RaisePropertyChanged(() => IconUri);  
             }  
         }  
 
         public string Area  
         {  
             get { return area; }  
             set  
             {  
                 area = value;  
                 RaisePropertyChanged(() => Area);  
             }  
         }  
 
         public string OwnerName  
         {  
             get { return ownerName; }  
             set  
             {  
                 ownerName = value;  
                 RaisePropertyChanged(() => OwnerName);  
             }  
         }  
 
 
         public string Speed  
         {  
             get { return speed; }  
             set  
             {  
                 speed = value;  
                 RaisePropertyChanged(() => Speed);  
             }  
         }  
 
         public string Duration  
         {  
             get { return duration; }  
             set  
             {  
                 duration = value;  
                 RaisePropertyChanged(() => Duration);  
             }  
         }  
     }  
 }  
 
 

ViewModelBase.cs

 using System;  
 using System.ComponentModel;  
 using System.Linq.Expressions;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     public class ViewModelBase : INotifyPropertyChanged  
     {  
         public ViewModelBase()  
         {  
         }  
 
         public event PropertyChangedEventHandler PropertyChanged;  
 
         protected virtual void RaisePropertyChanged(string propertyName)  
         {  
             PropertyChangedEventHandler handler = PropertyChanged;  
             if (handler != null)  
             {  
                 handler(this, new PropertyChangedEventArgs(propertyName));  
             }  
         }  
 
         protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> expreesion)  
         {  
             RaisePropertyChanged(((MemberExpression)expreesion.Body).Member.Name);  
         }  
     }  
 }  
 

Location.cs

 using System;  
 using System.Runtime.Serialization;  
 using ThinkGeo.MapSuite.Core;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     /// <summary>  
     /// This class specify the basic information for a location.  
     /// </summary>  
     [DataContract]  
     public class Location  
     {  
         private double speed;  
         private double latitude;  
         private double longitude;  
         private DateTime dateTime;  
 
         public Location()  
             : this(0, 0, 0, DateTime.Now)  
         { }  
 
         public Location(double longitude, double latitude, double speed, DateTime dateTime)  
         {  
             Longitude = longitude;  
             Latitude = latitude;  
             Speed = speed;  
             DateTime = dateTime;  
         }  
 
         [DataMember]  
         public double Longitude  
         {  
             get { return longitude; }  
             set { longitude = value; }  
         }  
 
         [DataMember]  
         public double Latitude  
         {  
             get { return latitude; }  
             set { latitude = value; }  
         }  
 
         [DataMember]  
         public double Speed  
         {  
             get { return speed; }  
             set { speed = value; }  
         }  
 
         [DataMember]  
         public DateTime DateTime  
         {  
             get { return dateTime; }  
             set { dateTime = value; }  
         }  
     }  
 }  
 

TrackingAccessProvider.cs

 using System;  
 using System.Linq;  
 using System.Collections.Generic;  
 using System.Collections.ObjectModel;  
 using System.Data;  
 using System.Data.OleDb;  
 using System.Globalization;  
 using System.Text;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     public class TrackingAccessProvider : TrackingDataProvider  
     {  
         private OleDbConnection dataConnection;  
 
         public TrackingAccessProvider(string databaseFilePath)  
         {  
             string connectionString = string.Format(CultureInfo.InvariantCulture, "Provider=Microsoft.Jet.OLEDB.4.0; Data Source='{0}'", databaseFilePath);  
             dataConnection = new OleDbConnection(connectionString);  
         }  
 
         public override Dictionary<int, Vehicle> GetCurrentVehicles(DateTime currentTime)  
         {  
             Dictionary<int, Vehicle> vehiclesList = new Dictionary<int, Vehicle>();  
             DataSet vehiclesDataSet = ExecuteQuery("Select * from Vehicle");  
 
             TimeSpan trackHistoryVehicleTimeSpan = TimeSpan.FromHours(8);  
             foreach (DataRow row in vehiclesDataSet.Tables[0].Rows)  
             {  
                 int vehicleId = Convert.ToInt32(row["VehicleId"], CultureInfo.InvariantCulture);  
                 Vehicle vehicle = GetCurrentVehicle(vehicleId, currentTime, trackHistoryVehicleTimeSpan);  
                 vehiclesList.Add(vehicle.Id, vehicle);  
             }  
 
             return vehiclesList;  
         }  
 
         private Vehicle GetCurrentVehicle(int vehicleId, DateTime currentTime, TimeSpan trackHistoryVehicleTimeSpan)  
         {  
             string sql =  "SELECT A.VehicleName, A.VehicleID, A.VehicleIconVirtualPath, B.Longitude, B.Latitude, B.[Date], B.Speed FROM (Vehicle A LEFT OUTER JOIN Location B ON A.VehicleID = B.VehicleID) WHERE (A.VehicleID = {0}) AND (B.[Date] <= #{1}# and B.[Date]>=#{2}#) ORDER BY A.VehicleID, B.[Date] DESC";  
             DateTime trackStartTime = currentTime.AddTicks(-trackHistoryVehicleTimeSpan.Ticks);  
             sql = String.Format(CultureInfo.InvariantCulture, sql, vehicleId, currentTime.ToString(CultureInfo.InvariantCulture), trackStartTime.ToString(CultureInfo.InvariantCulture));  
 
             Vehicle currentVechicle = new Vehicle(vehicleId);  
             DataSet currentLocations = null;  
             try  
             {  
                 // Get the locations from current time back to the passed time span  
                 currentLocations = ExecuteQuery(sql);  
                 Collection<double> historySpeeds = new Collection<double>();  
                 for (int rowIndex = 0; rowIndex < currentLocations.Tables[0].Rows.Count; rowIndex++)  
                 {  
                     DataRow dataRow = currentLocations.Tables[0].Rows[rowIndex];  
                     currentVechicle.VehicleIconVirtualPath = dataRow["VehicleIconVirtualPath"].ToString();  
 
                     double latitude = Convert.ToDouble(dataRow["Latitude"], CultureInfo.InvariantCulture);  
                     double longitude = Convert.ToDouble(dataRow["Longitude"], CultureInfo.InvariantCulture);  
                     double speed = Convert.ToDouble(dataRow["Speed"], CultureInfo.InvariantCulture);  
                     DateTime dateTime = Convert.ToDateTime(dataRow["Date"], CultureInfo.InvariantCulture);  
                     Location currentLocation = new Location(longitude, latitude, speed, dateTime);  
                     historySpeeds.Add(speed);  
 
                     if (rowIndex == 0)  
                     {  
                         string vehicleName = dataRow["VehicleName"].ToString();  
                         currentVechicle.Location = currentLocation;  
                         currentVechicle.Id = vehicleId;  
                         currentVechicle.VehicleName = vehicleName;  
                     }  
                     else  
                     {  
                         currentVechicle.HistoryLocations.Add(currentLocation);  
                     }  
                 }  
             }  
             finally  
             {  
                 if (currentLocations != null) currentLocations.Dispose();  
             }  
 
             return currentVechicle;  
         }  
 
         public override Collection<string> GetSpatialFences()  
         {  
             Collection<string> spatialFences = new Collection<string>();  
             DataSet dataSet = ExecuteQuery("Select * from SpatialFence");  
 
             foreach (DataRow row in dataSet.Tables[0].Rows)  
             {  
                 string wkt = row["FenceGeometry"].ToString();  
                 string id = row["FeatureID"].ToString();  
                 spatialFences.Add(wkt + "|" + id);  
             }  
             return spatialFences;  
         }  
 
         public void DeleteAndUpdateAndInsertSpatialFences(IEnumerable<string> excludeFeatureWktIds)  
         {  
             Dictionary<string, string> featureWktIds = new Dictionary<string, string>();  
             foreach (var item in excludeFeatureWktIds)  
             {  
                 var array = item.Split('|');  
                 if (array.Length == 2)  
                 {  
                     featureWktIds.Add(array[0], array[1]);  
                 }  
             }  
             DeleteSpatialFencesExcluding(featureWktIds.Values.ToList());  
             foreach (var item in featureWktIds)  
             {  
                 int result = UpdateSpatialFenceByFeature(item.Key, item.Value);  
                 if (result == 0)  
                 {  
                     InsertSpatialFence(item.Key, item.Value);  
                 }  
             }  
         }  
 
         public override void DeleteSpatialFencesExcluding(IEnumerable<string> excludeFeatureIds)  
         {  
             StringBuilder undeleteFeatureIds = new StringBuilder();  
             foreach (string undeleteFeatureId in excludeFeatureIds)  
             {  
                 undeleteFeatureIds.AppendFormat(CultureInfo.InvariantCulture, "'{0}',", undeleteFeatureId);  
             }  
             string sql = String.Format(CultureInfo.InvariantCulture,  
                 "DELETE FROM SpatialFence WHERE (FeatureID NOT IN ({0}))", undeleteFeatureIds.ToString().TrimEnd(','));  
             ExecuteNonQuery(sql);  
         }  
 
         public override int UpdateSpatialFenceByFeature(string wkt, string featureId)  
         {  
             int updatedSpatialFenceCount =  
                 ExecuteNonQuery(String.Format(CultureInfo.InvariantCulture,  
                     "UPDATE SpatialFence SET FenceGeometry = '{0}' WHERE (FeatureID = '{1}')", wkt, featureId));  
             return updatedSpatialFenceCount;  
         }  
 
         public override void InsertSpatialFence(string wkt, string featureId)  
         {  
             ExecuteNonQuery(String.Format(CultureInfo.InvariantCulture,  
                 "Insert into SpatialFence(FenceGeometry,FeatureID) values('{0}','{1}')", wkt, featureId));  
         }  
 
         private DataSet ExecuteQuery(string selectCommandText)  
         {  
             OleDbDataAdapter dataAdapter = null;  
             try  
             {  
                 dataAdapter = new OleDbDataAdapter(selectCommandText, dataConnection);  
                 dataConnection.Open();  
                 DataSet dataSet = new DataSet();  
                 dataSet.Locale = CultureInfo.InvariantCulture;  
                 dataAdapter.Fill(dataSet);  
                 return dataSet;  
             }  
             finally  
             {  
                 if (dataAdapter != null)  
                 {  
                     dataAdapter.Dispose();  
                 }  
                 if (dataConnection != null)  
                 {  
                     dataConnection.Close();  
                 }  
             }  
         }  
 
         private int ExecuteNonQuery(string cmdText)  
         {  
             OleDbCommand dataCommand = null;  
             int affectedRowNumber = 0;  
             try  
             {  
                 dataCommand = new OleDbCommand(cmdText, dataConnection);  
                 dataConnection.Open();  
                 affectedRowNumber = dataCommand.ExecuteNonQuery();  
             }  
             finally  
             {  
                 if (dataCommand != null) dataCommand.Dispose();  
                 if (dataConnection != null) dataConnection.Close();  
             }  
 
             return affectedRowNumber;  
         }  
 
         ~TrackingAccessProvider()  
         {  
             Dispose(false);  
         }  
 
         public override void Dispose()  
         {  
             Dispose(true);  
             GC.SuppressFinalize(this);  
         }  
 
         private void Dispose(bool flag)  
         {  
             if (flag)  
             {  
                 if (dataConnection != null)  
                 {  
                     dataConnection.Close();  
                     dataConnection.Dispose();  
                     dataConnection = null;  
                 }  
             }  
         }  
     }  
 }  
 

TrackingDataProvider.cs

 using System;  
 using System.Collections.Generic;  
 using System.Collections.ObjectModel;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     public abstract class TrackingDataProvider : IDisposable  
     {  
         public abstract Dictionary<int, Vehicle> GetCurrentVehicles(DateTime currentTime);  
 
         public abstract Collection<string> GetSpatialFences();  
 
         public abstract void DeleteSpatialFencesExcluding(IEnumerable<string> excludeFeatureIds);  
 
         public abstract int UpdateSpatialFenceByFeature(string wkt, string featureId);  
 
         public abstract void InsertSpatialFence(string wkt, string featureId);  
 
         public abstract void Dispose();  
     }  
 }  
 

Vehicle.cs

 using System.Collections.ObjectModel;  
 using System.Runtime.Serialization;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     /// <summary>  
     /// This class stands for a vehicle.  
     /// </summary>  
     [DataContract]  
     public class Vehicle  
     {  
         private int id;  
         private string name;  
         private string iconPath;  
         private Location location;  
         private Collection<Location> historyLocations;  
 
         private Vehicle()  
             : this(0)  
         { }  
 
         public Vehicle(int id)  
         {  
             Id = id;  
             name = string.Empty;  
             Location = new Location();  
             historyLocations = new Collection<Location>();  
         }  
 
         [DataMember]  
         public int Id  
         {  
             get { return id; }  
             set { id = value; }  
         }  
 
         [DataMember]  
         public Location Location  
         {  
             get { return location; }  
             set { location = value; }  
         }  
 
         [DataMember]  
         public Collection<Location> HistoryLocations  
         {  
             get { return historyLocations; }  
         }  
 
         [DataMember]  
         public string VehicleName  
         {  
             get { return name; }  
             set { name = value; }  
         }  
 
         [DataMember]  
         public string VehicleIconVirtualPath  
         {  
             get { return iconPath; }  
             set { iconPath = value; }  
         }  
 
         public int GetSpeedDuration()  
         {  
             int speedDuration = 0;  
             double lastSpeed = Location.Speed;  
             foreach (Location tempLocation in HistoryLocations)  
             {  
                 if (tempLocation.Speed == lastSpeed)  
                 {  
                     speedDuration++;  
                 }  
                 else  
                 {  
                     break;  
                 }  
             }  
 
             return speedDuration;  
         }  
 
         /// <summary>  
         /// If the Vehicle's speed is not 0 in the passed 4 minutes, we say it is in Motion.  
         /// </summary>  
         /// <returns>State of current vehicle.</returns>  
         public VehicleMotionState GetCurrentState()  
         {  
             VehicleMotionState vehicleState = VehicleMotionState.Idle;  
 
             if (Location.Speed != 0)  
             {  
                 vehicleState = VehicleMotionState.Motion;  
             }  
             else  
             {  
                 int locationIndex = 0;  
                 foreach (Location historyLocation in HistoryLocations)  
                 {  
                     if (locationIndex > 3)  
                     {  
                         break;  
                     }  
                     if (historyLocation.Speed != 0)  
                     {  
                         vehicleState = VehicleMotionState.Motion;  
                         break;  
                     }  
                     locationIndex++;  
                 }  
             }  
 
             return vehicleState;  
         }  
     }  
 }  
 
 

VehicleMotionState.cs

 using System.Runtime.Serialization;  
 
 namespace ThinkGeo.MapSuite.VehicleTracking  
 {  
     /// <summary>  
     /// This enumeration specifies the Possible states for Vehicles.  
     /// </summary>  
     [DataContract]  
     public enum VehicleMotionState  
     {  
         [DataMember]  
         Motion = 0,  
         [DataMember]  
         Idle = 1,  
     }  
 }  
 
source_code_silverlighteditionsample_vehicletracking_cs.zip.txt · Last modified: 2015/09/09 03:37 by admin