====== Source Code Xamarin Forms ProjectTemplates SiteSelection CS.zip ====== ====App.cs==== using System; using System.Collections.Generic; using System.Linq; using System.Text; using Xamarin.Forms; namespace SiteSelection { public class App : Application { public App() { InitializeStyles(); // The root page of your application MainPage = new NavigationPage(new MainPage { Title = "Site Selection" }); } protected override void OnStart() { // Handle when your app starts } protected override void OnSleep() { // Handle when your app sleeps } protected override void OnResume() { // Handle when your app resumes } private void InitializeStyles() { Application.Current.Resources = new ResourceDictionary(); Style settingsContainerStyle = new Style(typeof(Grid)); settingsContainerStyle.Setters.Add(new Setter { Property = Grid.BackgroundColorProperty, Value = Color.FromHex("#efefef") }); settingsContainerStyle.Setters.Add(new Setter { Property = Grid.PaddingProperty, Value = new Thickness(0, 5, 0, 5) }); Application.Current.Resources.Add("SettingsContainerStyle", settingsContainerStyle); Style settingsListLabelStyle = new Style(typeof(Label)); settingsListLabelStyle.Setters.Add(new Setter { Property = Label.TextColorProperty, Value = Color.Black }); settingsListLabelStyle.Setters.Add(new Setter { Property = Label.VerticalOptionsProperty, Value = LayoutOptions.End }); Application.Current.Resources.Add("SettingsListLabelStyle", settingsListLabelStyle); Style sampleButtonStyle = new Style(typeof(Button)); sampleButtonStyle.Setters.Add(new Setter { Property = Button.BackgroundColorProperty, Value = Color.FromHex("#e0e0e0") }); sampleButtonStyle.Setters.Add(new Setter { Property = Button.TextColorProperty, Value = Color.FromHex("#000000") }); Application.Current.Resources.Add("SampleButtonStyle", sampleButtonStyle); Style settingsContentStyle = new Style(typeof(Grid)); settingsContentStyle.Setters.Add(new Setter { Property = Grid.BackgroundColorProperty, Value = Color.White }); settingsContentStyle.Setters.Add(new Setter { Property = Grid.PaddingProperty, Value = new Thickness(5) }); Application.Current.Resources.Add("SettingsContentStyle", settingsContentStyle); Style settingsTitleStyle = new Style(typeof(Label)); settingsTitleStyle.Setters.Add(new Setter { Property = Label.TextColorProperty, Value = Color.Black }); settingsTitleStyle.Setters.Add(new Setter { Property = Label.FontSizeProperty, Value = 21 }); settingsTitleStyle.Setters.Add(new Setter { Property = Label.FontAttributesProperty, Value = FontAttributes.Bold }); Application.Current.Resources.Add("SettingsTitleStyle", settingsTitleStyle); Style settingsListGridStyle = new Style(typeof(Grid)); settingsListGridStyle.Setters.Add(new Setter { Property = Grid.PaddingProperty, Value = new Thickness(5, 0, 5, 0) }); Application.Current.Resources.Add("SettingsListGridStyle", settingsListGridStyle); Style settingsListLineStyle = new Style(typeof(Grid)); settingsListLineStyle.Setters.Add(new Setter { Property = Grid.BackgroundColorProperty, Value = Device.OnPlatform(Color.Transparent, Color.Black, Color.Transparent) }); Application.Current.Resources.Add("SettingsListLineStyle", settingsListLineStyle); } } } ====MainPageViewModel.cs==== using SiteSelection.Properties; using System.Collections.ObjectModel; using System.Linq; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.FormsEdition; using Xamarin.Forms; namespace SiteSelection { public partial class MainPageViewModel { private static readonly RectangleShape globeExtent = new RectangleShape(-10782584.5066971, 3916291.54400321, -10769504.2529497, 3907774.56943023); private IPlatformService platformsService; private MapView mapControl; private MarkerOverlay markerOverlay; private ShapeFileFeatureLayer restrictedLayer; private ShapeFileFeatureLayer hotelsLayer; private ShapeFileFeatureLayer schoolsLayer; private InMemoryFeatureLayer queryAreaLayer; private ShapeFileFeatureLayer restaurantsLayer; private ShapeFileFeatureLayer medicalFacilitesLayer; private ShapeFileFeatureLayer publicFacilitesLayer; private InMemoryFeatureLayer highlightFeatureLayer; public MainPageViewModel(MapView mapControl) { this.mapControl = mapControl; this.platformsService = DependencyService.Get(); InitializeMapControl(); InitializeMapTools(); InitializeOverlays(); SettingsPageViewModel.Instance.QueryButtonClicked += SettingsPageViewModel_QueryButtonClicked; SettingsPageViewModel.Instance.BaseMapTypeChanged += SettingsPageViewModel_BaseMapTypeChanged; } private void SettingsPageViewModel_BaseMapTypeChanged(object sender, System.EventArgs e) { OpenStreetMapOverlay osmOverlay = (OpenStreetMapOverlay)mapControl.Overlays[Resources.OSMOverlayName]; WorldMapKitOverlay wmkOverlay = (WorldMapKitOverlay)mapControl.Overlays[Resources.WorldMapKitOverlayName]; switch (SettingsPageViewModel.Instance.BaseMapType) { case BaseMapType.WorldMapKitRoad: osmOverlay.IsVisible = false; wmkOverlay.IsVisible = true; wmkOverlay.MapType = WorldMapKitMapType.Road; break; case BaseMapType.WorldMapKitAerial: osmOverlay.IsVisible = false; wmkOverlay.IsVisible = true; wmkOverlay.MapType = WorldMapKitMapType.Aerial; break; case BaseMapType.WorldMapKitAerialWithLabels: osmOverlay.IsVisible = false; wmkOverlay.IsVisible = true; wmkOverlay.MapType = WorldMapKitMapType.AerialWithLabels; break; case BaseMapType.OpenStreetMap: osmOverlay.IsVisible = true; wmkOverlay.IsVisible = false; break; default: break; } mapControl.Refresh(); } private void SettingsPageViewModel_QueryButtonClicked(object sender, System.EventArgs e) { RefreshQueryResult(); mapControl.Navigation.PopAsync(true); } private void TrackOverlay_TrackEnded(object sender, TrackEndedTrackInteractiveOverlayEventArgs e) { if (mapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Count > 0) { Feature centerFeature = mapControl.TrackOverlay.TrackShapeLayer.InternalFeatures[0]; mapControl.TrackOverlay.TrackShapeLayer.InternalFeatures.Clear(); MarkerOverlay highlightCenterMarkerOverlay = (MarkerOverlay)mapControl.Overlays[Resources.HighlightCenterMarkerOverlayKey]; highlightCenterMarkerOverlay.Markers.Clear(); Marker pinMarker = new Marker { ImageSource = SampleHelper.GetDataPath(@"Images/pin.png"), Position = (PointShape)centerFeature.GetShape() }; pinMarker.YOffset = -16; highlightCenterMarkerOverlay.Markers.Add(pinMarker); highlightCenterMarkerOverlay.Refresh(); mapControl.TrackOverlay.Refresh(); RefreshQueryResult(); } } private void RefreshQueryResult() { MarkerOverlay highlightCenterMarkerOverlay = (MarkerOverlay)mapControl.Overlays[Resources.HighlightCenterMarkerOverlayKey]; Marker marker = highlightCenterMarkerOverlay.Markers.FirstOrDefault(); if (marker != null) { MultipolygonShape queryArea = marker.Position.Buffer(SettingsPageViewModel.Instance.BufferedDistance, mapControl.MapUnit, DistanceUnit.Mile); queryAreaLayer.InternalFeatures.Clear(); queryAreaLayer.InternalFeatures.Add(new Feature(queryArea)); if (!SettingsPageViewModel.Instance.SelectedPoiFeatureLayer.IsOpen) SettingsPageViewModel.Instance.SelectedPoiFeatureLayer.Open(); Collection queryResultFeatures = SettingsPageViewModel.Instance.SelectedPoiFeatureLayer.FeatureSource.GetFeaturesWithinDistanceOf(queryArea, mapControl.MapUnit, DistanceUnit.Meter, 0.1, ReturningColumnsType.AllColumns); highlightFeatureLayer.Clear(); foreach (Feature resultFeature in FilterFeaturesByColumnValue(queryResultFeatures)) { highlightFeatureLayer.InternalFeatures.Add(resultFeature); } SettingsPageViewModel.Instance.QueriedFeatures.SafeClear(); foreach (Feature highLightFeature in highlightFeatureLayer.InternalFeatures) { SettingsPageViewModel.Instance.QueriedFeatures.Add(new PotentialSimilarSiteItem(highLightFeature)); } mapControl.Overlays[Resources.PoiOverlayKey].Refresh(); } } private void ClearQueryResult() { MarkerOverlay highlightCenterMarkerOverlay = (MarkerOverlay)mapControl.Overlays[Resources.HighlightCenterMarkerOverlayKey]; highlightFeatureLayer.Clear(); queryAreaLayer.InternalFeatures.Clear(); highlightCenterMarkerOverlay.Markers.Clear(); SettingsPageViewModel.Instance.QueriedFeatures.SafeClear(); highlightCenterMarkerOverlay.Refresh(); mapControl.Overlays[Resources.PoiOverlayKey].Refresh(); } private void InitializeMapControl() { mapControl.MapUnit = GeographyUnit.Meter; mapControl.ZoomLevelSet = new BingMapsZoomLevelSet(); mapControl.CurrentExtent = globeExtent; mapControl.TrackOverlay.TrackEnded += TrackOverlay_TrackEnded; } private void InitializeOverlays() { WorldMapKitOverlay worldMapKitOverlay = new WorldMapKitOverlay(); worldMapKitOverlay.Name = Resources.WorldMapKitOverlayName; worldMapKitOverlay.IsVisible = true; worldMapKitOverlay.Projection = WorldMapKitProjection.SphericalMercator; mapControl.Overlays.Add(Resources.WorldMapKitOverlayName, worldMapKitOverlay); OpenStreetMapOverlay openStreetMapOverlay = new OpenStreetMapOverlay(); openStreetMapOverlay.Name = Resources.OSMOverlayName; openStreetMapOverlay.IsVisible = false; openStreetMapOverlay.TileCache = platformsService.GetOverlayTileCache(openStreetMapOverlay); openStreetMapOverlay.TileCache.TileMatrix.BoundingBoxUnit = GeographyUnit.Meter; openStreetMapOverlay.TileCache.TileMatrix.BoundingBox = openStreetMapOverlay.GetBoundingBox(); mapControl.Overlays.Add(Resources.OSMOverlayName, openStreetMapOverlay); LayerOverlay customOverlay = new LayerOverlay(); customOverlay.Name = Resources.CustomOverlayKey; customOverlay.TileType = TileType.SingleTile; mapControl.Overlays.Add(Resources.CustomOverlayKey, customOverlay); ManagedProj4Projection wgs84ToMercatorProj4Projection = new ManagedProj4Projection(); wgs84ToMercatorProj4Projection.InternalProjectionParametersString = Proj4Projection.GetDecimalDegreesParametersString(); wgs84ToMercatorProj4Projection.ExternalProjectionParametersString = Proj4Projection.GetSphericalMercatorParametersString(); wgs84ToMercatorProj4Projection.Open(); restrictedLayer = new ShapeFileFeatureLayer(SampleHelper.GetDataPath("CityLimitPolygon.shp")); restrictedLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(new AreaStyle(new GeoPen(GeoColor.SimpleColors.White, 5.5f), new GeoSolidBrush(GeoColor.SimpleColors.Transparent))); restrictedLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(new AreaStyle(new GeoPen(GeoColor.SimpleColors.Red, 1.5f) { DashStyle = LineDashStyle.Dash }, new GeoSolidBrush(GeoColor.SimpleColors.Transparent))); restrictedLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; restrictedLayer.FeatureSource.Projection = wgs84ToMercatorProj4Projection; customOverlay.Layers.Add(Resources.RestrictedLayerKey, restrictedLayer); LayerOverlay poiOverlay = new LayerOverlay(); poiOverlay.TileType = TileType.SingleTile; mapControl.Overlays.Add(Resources.PoiOverlayKey, poiOverlay); hotelsLayer = new ShapeFileFeatureLayer(SampleHelper.GetDataPath(@"POIs/Hotels.shp")); hotelsLayer.Name = Resources.HotelsLayerKey; hotelsLayer.Transparency = 120f; hotelsLayer.ZoomLevelSet.ZoomLevel10.DefaultPointStyle = new PointStyle(new GeoImage(SampleHelper.GetDataPath(@"Images/Hotel.png"))); hotelsLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; hotelsLayer.FeatureSource.Projection = wgs84ToMercatorProj4Projection; poiOverlay.Layers.Add(Resources.HotelsLayerKey, hotelsLayer); medicalFacilitesLayer = new ShapeFileFeatureLayer(SampleHelper.GetDataPath(@"POIs/Medical_Facilities.shp")); medicalFacilitesLayer.Name = Resources.MedicalFacilitesLayerKey; medicalFacilitesLayer.Transparency = 120f; medicalFacilitesLayer.ZoomLevelSet.ZoomLevel10.DefaultPointStyle = new PointStyle(new GeoImage(SampleHelper.GetDataPath(@"Images/DrugStore.png"))); medicalFacilitesLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; medicalFacilitesLayer.FeatureSource.Projection = wgs84ToMercatorProj4Projection; poiOverlay.Layers.Add(Resources.MedicalFacilitesLayerKey, medicalFacilitesLayer); publicFacilitesLayer = new ShapeFileFeatureLayer(SampleHelper.GetDataPath(@"POIs/Public_Facilities.shp")); publicFacilitesLayer.Name = Resources.PublicFacilitesLayerKey; publicFacilitesLayer.Transparency = 120f; publicFacilitesLayer.ZoomLevelSet.ZoomLevel10.DefaultPointStyle = new PointStyle(new GeoImage(SampleHelper.GetDataPath(@"Images/public_facility.png"))); publicFacilitesLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; publicFacilitesLayer.FeatureSource.Projection = wgs84ToMercatorProj4Projection; poiOverlay.Layers.Add(Resources.PublicFacilitesLayerKey, publicFacilitesLayer); restaurantsLayer = new ShapeFileFeatureLayer(SampleHelper.GetDataPath(@"POIs/Restaurants.shp")); restaurantsLayer.Name = Resources.RestaurantsLayerKey; restaurantsLayer.Transparency = 120f; restaurantsLayer.ZoomLevelSet.ZoomLevel10.DefaultPointStyle = new PointStyle(new GeoImage(SampleHelper.GetDataPath(@"Images/restaurant.png"))); restaurantsLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; restaurantsLayer.FeatureSource.Projection = wgs84ToMercatorProj4Projection; poiOverlay.Layers.Add(Resources.RestaurantsLayerKey, restaurantsLayer); schoolsLayer = new ShapeFileFeatureLayer(SampleHelper.GetDataPath(@"POIs/Schools.shp")); schoolsLayer.Name = Resources.SchoolsLayerKey; schoolsLayer.Transparency = 120f; schoolsLayer.ZoomLevelSet.ZoomLevel10.DefaultPointStyle = new PointStyle(new GeoImage(SampleHelper.GetDataPath(@"Images/school.png"))); schoolsLayer.ZoomLevelSet.ZoomLevel10.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; schoolsLayer.FeatureSource.Projection = wgs84ToMercatorProj4Projection; poiOverlay.Layers.Add(Resources.SchoolsLayerKey, schoolsLayer); highlightFeatureLayer = new InMemoryFeatureLayer(); highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = new PointStyle(new GeoImage(SampleHelper.GetDataPath(@"Images/selectedHalo.png"))); highlightFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; queryAreaLayer = new InMemoryFeatureLayer(); queryAreaLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(new GeoColor(120, GeoColor.FromHtml("#1749c9")), GeoColor.FromHtml("#fefec1"), 3, LineDashStyle.Solid); queryAreaLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; poiOverlay.Layers.Add(Resources.QueryAreaLayerKey, queryAreaLayer); markerOverlay = new MarkerOverlay(); mapControl.Overlays.Add(Resources.HighlightCenterMarkerOverlayKey, markerOverlay); SettingsPageViewModel.Instance.PoiFeatureLayers.Add(hotelsLayer.Name, hotelsLayer); SettingsPageViewModel.Instance.PoiFeatureLayers.Add(medicalFacilitesLayer.Name, medicalFacilitesLayer); SettingsPageViewModel.Instance.PoiFeatureLayers.Add(restaurantsLayer.Name, restaurantsLayer); SettingsPageViewModel.Instance.PoiFeatureLayers.Add(schoolsLayer.Name, schoolsLayer); SettingsPageViewModel.Instance.SelectedPoiFeatureLayer = SettingsPageViewModel.Instance.PoiFeatureLayers[hotelsLayer.Name]; poiOverlay.Layers.Add(Resources.HighlightFeatureLayerKey, highlightFeatureLayer); } private void InitializeMapTools() { mapControl.MapTools.CenterCoordinate.IsEnabled = false; mapControl.MapTools.ZoomMapTool.IsGlobeButtonVisiable = true; mapControl.MapTools.ZoomMapTool.GlobeExtent = globeExtent; } private static Collection FilterFeaturesByColumnValue(Collection queryResultFeatures) { Collection resultFeatures = new Collection(); foreach (Feature feature in queryResultFeatures) { if (SettingsPageViewModel.Instance.SelectedPoiFilterItem.Equals(Resources.AllFeatureKey)) { resultFeatures.Add(feature); } else if (SettingsPageViewModel.Instance.SelectedPoiFilterItem.Equals(feature.ColumnValues[SettingsPageViewModel.Instance.SelectedPoiColumnName])) { resultFeatures.Add(feature); } else if (SettingsPageViewModel.Instance.SelectedPoiFeatureLayer.Name.Equals(Resources.HotelsLayerKey)) { string[] values = SettingsPageViewModel.Instance.SelectedPoiFilterItem.Split('~'); double min = 0, max = 0, value = 0; if (double.TryParse(values[0], out min) && double.TryParse(values[1], out max) && double.TryParse(feature.ColumnValues[SettingsPageViewModel.Instance.SelectedPoiColumnName], out value)) { if (min < value && value < max) { resultFeatures.Add(feature); } } } } return resultFeatures; } } } ====MainPageViewModel_Commands.cs==== using ThinkGeo.MapSuite.FormsEdition; using Xamarin.Forms; namespace SiteSelection { public partial class MainPageViewModel : ViewModelBase { private OperationMode operationMode; private Command clearCommand; private Command queryCommand; private Command panCommand; private Command pinCommand; private Command settingsCommand; public Command SettingsCommand { get { settingsCommand = settingsCommand ?? new Command(() => { SettingsPage.Instance.BackupOldSettings(); mapControl.Navigation.PushAsync(SettingsPage.Instance, true); }); return settingsCommand; } } public Command PinCommand { get { pinCommand = pinCommand ?? new Command(() => OperationMode = OperationMode.Pin); return pinCommand; } } public Command PanCommand { get { panCommand = panCommand ?? new Command(() => OperationMode = OperationMode.Pan); return panCommand; } } public OperationMode OperationMode { get { return operationMode; } set { if (operationMode != value) { operationMode = value; switch (operationMode) { case OperationMode.Pan: mapControl.TrackOverlay.TrackMode = TrackMode.None; break; case OperationMode.Pin: mapControl.TrackOverlay.TrackMode = TrackMode.Point; break; default: break; } OnPropertyChanged(() => OperationMode); } } } public Command ClearCommand { get { clearCommand = clearCommand ?? new Command(() => { ClearQueryResult(); }); return clearCommand; } } public Command QueryCommand { get { queryCommand = queryCommand ?? new Command(() => { RefreshQueryResult(); PotentialSimilarSitesPage page = new PotentialSimilarSitesPage(); page.ToolbarItems.Add(new ToolbarItem("? Back", "quit", () => { page.Navigation.PopAsync(true); })); mapControl.Navigation.PushAsync(page, true); }); return queryCommand; } } } } ====MainPage.xaml.cs==== using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.FormsEdition; using Xamarin.Forms; namespace SiteSelection { public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); MapView mapView = new MapView(); mapContainer.Content = mapView; BindingContext = new MainPageViewModel(mapView); MessagingCenter.Subscribe(SettingsPageViewModel.Instance, "ZOOMTOFEATURE", (s, f) => { mapView.ZoomTo(f); }); } } } ====BaseMapTypeToNameConverter.cs==== using System; using Xamarin.Forms; namespace SiteSelection { public class BaseMapTypeToNameConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value is BaseMapType) { BaseMapType settingType = (BaseMapType)value; switch (settingType) { case BaseMapType.WorldMapKitRoad: return "World Map Kit Road"; case BaseMapType.WorldMapKitAerial: return "World Map Kit Aerial"; case BaseMapType.WorldMapKitAerialWithLabels: return "World Map Kit Aerial With Labels"; case BaseMapType.OpenStreetMap: return "Open Street Map"; } } else { BaseMapType mapType; string baseMapTypeString = value.ToString().Replace(" ", ""); if (Enum.TryParse(baseMapTypeString, true, out mapType)) return mapType; } return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return Convert(value, targetType, parameter, culture); } } } ====CollectionToCountConverter.cs==== using System; using System.Collections; using Xamarin.Forms; namespace SiteSelection { public class CollectionToCountConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { ICollection collection = (ICollection)value; return collection.Count.ToString(); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } } ====FeatureToColumnValueConverter.cs==== using System; using ThinkGeo.MapSuite.Core; using Xamarin.Forms; namespace SiteSelection { class FeatureToColumnValueConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string result = string.Empty; Feature feature = value as Feature; if (feature != null && feature.ColumnValues.ContainsKey("Name")) { result = feature.ColumnValues["Name"]; } return result; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } } ====OperationModeToImageSourceConverter.cs==== using System; using Xamarin.Forms; namespace SiteSelection { public class OperationModeToImageSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string operationParameter = (string)parameter; if (value is OperationMode) { OperationMode operationMode = (OperationMode)value; switch (operationMode) { case OperationMode.Pin: if (operationParameter.Equals("PIN", StringComparison.OrdinalIgnoreCase)) { return new FileImageSource { File = Device.OnPlatform("Icons/pin_selected.png", "pin_selected", string.Empty) }; } else { return new FileImageSource { File = Device.OnPlatform("Icons/pan.png", "pan", string.Empty) }; } case OperationMode.Pan: default: if (operationParameter.Equals("PAN", StringComparison.OrdinalIgnoreCase)) { return new FileImageSource { File = Device.OnPlatform("Icons/pan_selected.png", "pan_selected", string.Empty) }; } else { return new FileImageSource { File = Device.OnPlatform("Icons/pin.png", "pin", string.Empty) }; } } } return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } } ====SettingsTypeToNameConverter.cs==== using System; using Xamarin.Forms; namespace SiteSelection { public class SettingsTypeToNameConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value is SettingType) { SettingType settingType = (SettingType)value; switch (settingType) { case SettingType.BaseMap: return "Base Map"; case SettingType.FilterInfo: return "Filter Type"; case SettingType.BufferedDistance: return "Buffered Distance"; } } else { switch (value.ToString()) { case "Base Map": return SettingType.BaseMap; case "Filter Type": return SettingType.FilterInfo; case "Buffered Distance": return SettingType.BufferedDistance; } } return null; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return Convert(value, targetType, parameter, culture); } } } ====BaseMapType.cs==== namespace SiteSelection { public enum BaseMapType { WorldMapKitRoad = 0, WorldMapKitAerial = 1, WorldMapKitAerialWithLabels = 2, OpenStreetMap = 3, } } ====OperationMode.cs==== namespace SiteSelection { public enum OperationMode { Pan = 0, Pin = 1 } } ====PotentialSimilarSiteItem.cs==== using ThinkGeo.MapSuite.Core; using Xamarin.Forms; namespace SiteSelection { public class PotentialSimilarSiteItem { private Command searchSiteCommand; private Feature feature; public PotentialSimilarSiteItem(Feature feature) { this.feature = feature; } public Feature Feature { get { return feature; } set { feature = value; } } } } ====SettingType.cs==== namespace SiteSelection { public enum SettingType { BaseMap = 0, FilterInfo = 1, BufferedDistance = 2 } } ====AssemblyInfo.cs==== using System.Resources; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly:|AssemblyTitle("SiteSelection")] [assembly: AssemblyDescription("")] [assembly:|AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly:|AssemblyProduct("SiteSelection")] [assembly: AssemblyCopyright("Copyright © 2015")] [assembly:|AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly:|NeutralResourcesLanguage("en")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly:|AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly:|AssemblyFileVersion("1.0.0.0")] ====Resources.Designer.cs==== //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.34014 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace SiteSelection.Properties { using System; using System.Reflection; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder",|"4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance",|"CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SiteSelection.Properties.Resources", typeof(Resources).GetTypeInfo().Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } /// /// Looks up a localized string similar to All. /// internal static string AllFeatureKey { get { return ResourceManager.GetString("AllFeatureKey", resourceCulture); } } /// /// Looks up a localized string similar to Bing Maps Aerial. /// internal static string BingMapsAerialOverlayName { get { return ResourceManager.GetString("BingMapsAerialOverlayName", resourceCulture); } } /// /// Looks up a localized string similar to Bing Maps Road. /// internal static string BingMapsRoadOverlayName { get { return ResourceManager.GetString("BingMapsRoadOverlayName", resourceCulture); } } /// /// Looks up a localized string similar to custom. /// internal static string CustomOverlayKey { get { return ResourceManager.GetString("CustomOverlayKey", resourceCulture); } } /// /// Looks up a localized string similar to Distance. /// internal static string DistanceKey { get { return ResourceManager.GetString("DistanceKey", resourceCulture); } } /// /// Looks up a localized string similar to DistanceUnit. /// internal static string DistanceUnitKey { get { return ResourceManager.GetString("DistanceUnitKey", resourceCulture); } } /// /// Looks up a localized string similar to DriveTime. /// internal static string DriveTimeInMinutesKey { get { return ResourceManager.GetString("DriveTimeInMinutesKey", resourceCulture); } } /// /// Looks up a localized string similar to HighlightCenterMarkerOverlay. /// internal static string HighlightCenterMarkerOverlayKey { get { return ResourceManager.GetString("HighlightCenterMarkerOverlayKey", resourceCulture); } } /// /// Looks up a localized string similar to HighlightFeatureLayer. /// internal static string HighlightFeatureLayerKey { get { return ResourceManager.GetString("HighlightFeatureLayerKey", resourceCulture); } } /// /// Looks up a localized string similar to Hotels. /// internal static string HotelsLayerKey { get { return ResourceManager.GetString("HotelsLayerKey", resourceCulture); } } /// /// Looks up a localized string similar to Medical Facilites. /// internal static string MedicalFacilitesLayerKey { get { return ResourceManager.GetString("MedicalFacilitesLayerKey", resourceCulture); } } /// /// Looks up a localized string similar to Open Street Map. /// internal static string OSMOverlayName { get { return ResourceManager.GetString("OSMOverlayName", resourceCulture); } } /// /// Looks up a localized string similar to Poi. /// internal static string PoiOverlayKey { get { return ResourceManager.GetString("PoiOverlayKey", resourceCulture); } } /// /// Looks up a localized string similar to Public Facilites. /// internal static string PublicFacilitesLayerKey { get { return ResourceManager.GetString("PublicFacilitesLayerKey", resourceCulture); } } /// /// Looks up a localized string similar to QueryArea. /// internal static string QueryAreaLayerKey { get { return ResourceManager.GetString("QueryAreaLayerKey", resourceCulture); } } /// /// Looks up a localized string similar to Restaurants. /// internal static string RestaurantsLayerKey { get { return ResourceManager.GetString("RestaurantsLayerKey", resourceCulture); } } /// /// Looks up a localized string similar to restricted. /// internal static string RestrictedLayerKey { get { return ResourceManager.GetString("RestrictedLayerKey", resourceCulture); } } /// /// Looks up a localized string similar to ScaleBar. /// internal static string ScaleBarLayerKey { get { return ResourceManager.GetString("ScaleBarLayerKey", resourceCulture); } } /// /// Looks up a localized string similar to Schools. /// internal static string SchoolsLayerKey { get { return ResourceManager.GetString("SchoolsLayerKey", resourceCulture); } } /// /// Looks up a localized string similar to PathFilename. /// internal static string StreetShapePathFilenameKey { get { return ResourceManager.GetString("StreetShapePathFilenameKey", resourceCulture); } } /// /// Looks up a localized string similar to World Map Kit. /// internal static string WorldMapKitOverlayName { get { return ResourceManager.GetString("WorldMapKitOverlayName", resourceCulture); } } } } ====IPlatformService.cs==== using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.FormsEdition; namespace SiteSelection { public interface IPlatformService { BitmapTileCache GetOverlayTileCache(TileOverlay tileOverlay); } } ====SampleHelper.cs==== using System.Collections.ObjectModel; using System.IO; using Xamarin.Forms; namespace SiteSelection { public static class SampleHelper { public static string GetDataPath(string fileName) { string result = string.IsNullOrEmpty(SampleDataDictionary) ? Path.Combine(AssetsDataDictionary, fileName) : Path.Combine(SampleDataDictionary, AssetsDataDictionary, fileName); return result; } public static string SampleDataDictionary { get { return Device.OnPlatform(string.Empty, @"mnt/sdcard/MapSuiteSampleData/SiteSelection", string.Empty); } } public static string AssetsDataDictionary { get { return Device.OnPlatform("AppData", "AppData", string.Empty); } } public static void SafeClear(this ObservableCollection items, int index = 0) { while (items.Count > index) { items.RemoveAt(index); } } } } ====SettingItem.cs==== namespace SiteSelection { public class SettingItem : ViewModelBase { private string title; private SettingType settingType; public SettingItem(SettingType settingType, string title) { SettingType = settingType; Value = title; } public SettingType SettingType { get { return settingType; } set { settingType = value; OnPropertyChanged(() => SettingType); } } public string Value { get { return title; } set { title = value; OnPropertyChanged(() => Value); } } } } ====SettingsPageViewModel.cs==== using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using ThinkGeo.MapSuite.Core; using Xamarin.Forms; namespace SiteSelection { public class SettingsPageViewModel : ViewModelBase { public event EventHandler CloseButtonClicked; public event EventHandler QueryButtonClicked; public event EventHandler BaseMapTypeChanged; private int bufferedDistance; private BaseMapType baseMapType; private SettingItem selectedItem; private Collection bufferedDistances; private Collection baseMapTypes; private ObservableCollection settingItems; private GeoCollection poiFeatureLayers; private ObservableCollection poiFilterItems; private ShapeFileFeatureLayer selectedPoiFeatureLayer; private string selectedPoiFilterItem; private string selectedPoiColumnName; private ObservableCollection queriedFeatures; private Command queryCommand; private Command closeCommand; private static SettingsPageViewModel instance; protected SettingsPageViewModel() { SelectedPoiColumnName = "ROOMS"; SelectedPoiFilterItem = Properties.Resources.AllFeatureKey; BufferedDistance = 2; BaseMapType = BaseMapType.WorldMapKitRoad; } public static SettingsPageViewModel Instance { get { instance = instance ?? new SettingsPageViewModel(); return instance; } } public Command CloseCommand { get { return closeCommand ?? (closeCommand = new Command(() => { OnCloseButtonClicked(); })); } } public Command QueryCommand { get { return queryCommand ?? (queryCommand = new Command(() => { OnQueryButtonClicked(); })); } } public BaseMapType BaseMapType { get { return baseMapType; } set { if (baseMapType != value) { baseMapType = value; OnBaseMapTypeChanged(); OnPropertyChanged(() => BaseMapType); } } } public ObservableCollection QueriedFeatures { get { queriedFeatures = queriedFeatures ?? new ObservableCollection(); return queriedFeatures; } } public Collection BaseMapTypes { get { baseMapTypes = baseMapTypes ?? new Collection(Enum.GetValues(typeof(BaseMapType)).Cast().ToList()); return baseMapTypes; } } public GeoCollection PoiFeatureLayers { get { return poiFeatureLayers ?? (poiFeatureLayers = new GeoCollection()); } } public string SelectedPoiColumnName { get { return selectedPoiColumnName; } set { selectedPoiColumnName = value; } } public int BufferedDistance { get { return bufferedDistance; } set { bufferedDistance = value; OnPropertyChanged(() => BufferedDistance); } } public Collection BufferedDistances { get { bufferedDistances = bufferedDistances ?? new Collection { 2, 3, 4, 6, 8, 10 }; return bufferedDistances; } } public ObservableCollection SettingItems { get { settingItems = settingItems ?? new ObservableCollection { new SettingItem(SettingType.BaseMap, "World Map Kit"), new SettingItem(SettingType.FilterInfo, "Hotels : Rooms / All"), new SettingItem(SettingType.BufferedDistance, "2 miles"), }; return settingItems; } } public SettingItem SelectedItem { get { return selectedItem; } set { selectedItem = value; OnPropertyChanged(() => SelectedItem); } } public ShapeFileFeatureLayer SelectedPoiFeatureLayer { get { return selectedPoiFeatureLayer; } set { if (selectedPoiFeatureLayer != value) { selectedPoiFeatureLayer = value; PoiFilterItems.SafeClear(1); SelectedPoiColumnName = GetDefaultColumnNameByPoiType(); if (PoiFilterItems.Count == 0) { PoiFilterItems.Add(Properties.Resources.AllFeatureKey); } if (SelectedPoiColumnName.Equals("ROOMS")) { PoiFilterItems.Add("1 ~ 50"); PoiFilterItems.Add("50 ~ 100"); PoiFilterItems.Add("100 ~ 150"); PoiFilterItems.Add("150 ~ 200"); PoiFilterItems.Add("200 ~ 300"); PoiFilterItems.Add("300 ~ 400"); PoiFilterItems.Add("400 ~ 500"); PoiFilterItems.Add(">= 500"); } else { SelectedPoiFeatureLayer.Open(); IEnumerable distinctColumnValues = SelectedPoiFeatureLayer.FeatureSource.GetDistinctColumnValues(SelectedPoiColumnName).Select(v => v.ColumnValue); foreach (var distinctColumnValue in distinctColumnValues.Where(v => !string.IsNullOrEmpty(v))) { PoiFilterItems.Add(distinctColumnValue); } } } OnPropertyChanged(() => SelectedPoiFeatureLayer); } } public ObservableCollection PoiFilterItems { get { return poiFilterItems ?? (poiFilterItems = new ObservableCollection()); } } public string SelectedPoiFilterItem { get { return selectedPoiFilterItem; } set { selectedPoiFilterItem = value; OnPropertyChanged(() => SelectedPoiFilterItem); } } protected virtual void OnCloseButtonClicked() { EventHandler handler = CloseButtonClicked; if (handler != null) { handler(this, new EventArgs()); } } protected virtual void OnQueryButtonClicked() { EventHandler handler = QueryButtonClicked; if (handler != null) { handler(this, new EventArgs()); } } protected virtual void OnBaseMapTypeChanged() { EventHandler handler = BaseMapTypeChanged; if (handler != null) { handler(this, new EventArgs()); } } private string GetDefaultColumnNameByPoiType() { string result = string.Empty; if (SelectedPoiFeatureLayer.Name.Equals(Properties.Resources.RestaurantsLayerKey)) { result = "FoodType"; } else if (SelectedPoiFeatureLayer.Name.Equals(Properties.Resources.MedicalFacilitesLayerKey) || SelectedPoiFeatureLayer.Name.Equals(Properties.Resources.SchoolsLayerKey)) { result = "TYPE"; } else if (SelectedPoiFeatureLayer.Name.Equals(Properties.Resources.PublicFacilitesLayerKey)) { result = "AGENCY"; } else if (SelectedPoiFeatureLayer.Name.Equals(Properties.Resources.HotelsLayerKey)) { result = "ROOMS"; } return result; } } } ====ViewModelBase.cs==== using System; using System.ComponentModel; using System.Linq.Expressions; namespace SiteSelection { public abstract class ViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(Expression> exp) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { string propertyName = ((MemberExpression)exp.Body).Member.Name; handler(this, new PropertyChangedEventArgs(propertyName)); } } } } ====BaseMapsPage.xaml.cs==== using System.Globalization; using Xamarin.Forms; namespace SiteSelection { public partial class BaseMapsPage : ContentPage { private static BaseMapTypeToNameConverter nameConverter = new BaseMapTypeToNameConverter(); public BaseMapsPage() { InitializeComponent(); BindingContext = SettingsPageViewModel.Instance; } private void BaseMapTypeList_ItemTapped(object sender, ItemTappedEventArgs e) { BaseMapType baseMapType = (BaseMapType)e.Item; SettingsPageViewModel.Instance.BaseMapType = baseMapType; SettingsPageViewModel.Instance.SettingItems[0].Value = nameConverter.Convert(baseMapType, typeof(BaseMapType), null, CultureInfo.InvariantCulture).ToString(); Navigation.PopAsync(true); } } } ====BufferedDistancePage.xaml.cs==== using System.Globalization; using Xamarin.Forms; namespace SiteSelection { public partial class BufferedDistancePage : ContentPage { public BufferedDistancePage() { InitializeComponent(); BindingContext = SettingsPageViewModel.Instance; } private void BufferedDistancesListItemTapped(object sender, ItemTappedEventArgs e) { int bufferedDistance = (int)e.Item; SettingsPageViewModel.Instance.BufferedDistance = bufferedDistance; SettingsPageViewModel.Instance.SettingItems[2].Value = string.Format(CultureInfo.InvariantCulture, "{0} Miles", bufferedDistance); Navigation.PopAsync(true); } } } ====FilterPoiFeatureLayerPage.xaml.cs==== using Xamarin.Forms; namespace SiteSelection { public partial class FilterPoiFeatureLayerPage : ContentPage { private SettingsPageViewModel viewModel; public FilterPoiFeatureLayerPage() { InitializeComponent(); BindingContext = viewModel = SettingsPageViewModel.Instance; } private async void FilterInfoListItemTapped(object sender, ItemTappedEventArgs e) { PoiFilterItemPage page = new PoiFilterItemPage(); await Navigation.PushAsync(page, true); } } } ====PoiFilterItemPage.xaml.cs==== using Xamarin.Forms; namespace SiteSelection { public partial class PoiFilterItemPage : ContentPage { private SettingsPageViewModel viewModel; public PoiFilterItemPage() { InitializeComponent(); BindingContext = viewModel = SettingsPageViewModel.Instance; } private async void FilterColumnInfoListItemTapped(object sender, ItemTappedEventArgs e) { viewModel.SettingItems[1].Value = string.Format("{0} : {1} / {2}", viewModel.SelectedPoiFeatureLayer.Name, viewModel.SelectedPoiColumnName, viewModel.SelectedPoiFilterItem); Navigation.RemovePage(Navigation.NavigationStack[Navigation.NavigationStack.Count|- 2]); await Navigation.PopAsync(true); } } } ====PotentialSimilarSitesPage.xaml.cs==== using Xamarin.Forms; namespace SiteSelection { public partial class PotentialSimilarSitesPage : ContentPage { public PotentialSimilarSitesPage() { InitializeComponent(); BindingContext = SettingsPageViewModel.Instance; } private void QueriedFeaturesListItemTapped(object sender, ItemTappedEventArgs e) { Navigation.PopToRootAsync(true); MessagingCenter.Send(SettingsPageViewModel.Instance, "ZOOMTOFEATURE", ((PotentialSimilarSiteItem)e.Item).Feature); } } } ====SettingsPage.xaml.cs==== using System.Globalization; using ThinkGeo.MapSuite.Core; using Xamarin.Forms; namespace SiteSelection { public partial class SettingsPage : ContentPage { private static SettingsPage instance; private int oldBufferDistance; private string oldSelectedPoiColumnName; private BaseMapType oldBaseMapType; private string oldSelectedPoiFilterItem; private ShapeFileFeatureLayer oldSelectedPoiFeatureLayer; protected SettingsPage() { InitializeComponent(); BindingContext = SettingsPageViewModel.Instance; SettingsPageViewModel.Instance.CloseButtonClicked += SettingsPageViewModel_CloseButtonClicked; } public static SettingsPage Instance { get { instance = instance ?? new SettingsPage(); return instance; } } private void SettingsPageViewModel_CloseButtonClicked(object sender, System.EventArgs e) { SettingsPageViewModel.Instance.BufferedDistance = oldBufferDistance; SettingsPageViewModel.Instance.SelectedPoiColumnName = oldSelectedPoiColumnName; SettingsPageViewModel.Instance.BaseMapType = oldBaseMapType; SettingsPageViewModel.Instance.SelectedPoiFilterItem = oldSelectedPoiFilterItem; SettingsPageViewModel.Instance.SelectedPoiFeatureLayer = oldSelectedPoiFeatureLayer; BaseMapTypeToNameConverter nameConverter = new BaseMapTypeToNameConverter(); SettingsPageViewModel.Instance.SettingItems[0].Value = nameConverter.Convert(SettingsPageViewModel.Instance.BaseMapType, typeof(BaseMapType), null, CultureInfo.InvariantCulture).ToString(); SettingsPageViewModel.Instance.SettingItems[1].Value = string.Format("{0} : {1} / {2}", SettingsPageViewModel.Instance.SelectedPoiFeatureLayer.Name, SettingsPageViewModel.Instance.SelectedPoiColumnName, SettingsPageViewModel.Instance.SelectedPoiFilterItem); SettingsPageViewModel.Instance.SettingItems[2].Value = string.Format(CultureInfo.InvariantCulture, "{0} Miles", SettingsPageViewModel.Instance.BufferedDistance); Navigation.PopAsync(true); } private void SettingList_ItemTapped(object sender, ItemTappedEventArgs e) { SettingItem tappedItem = (SettingItem)e.Item; switch (tappedItem.SettingType) { case SettingType.BaseMap: Navigation.PushAsync(new BaseMapsPage(), true); break; case SettingType.FilterInfo: Navigation.PushAsync(new FilterPoiFeatureLayerPage(), true); break; case SettingType.BufferedDistance: Navigation.PushAsync(new BufferedDistancePage(), true); break; default: break; } } protected override void OnDisappearing() { base.OnDisappearing(); } public void BackupOldSettings() { oldBufferDistance = SettingsPageViewModel.Instance.BufferedDistance; oldSelectedPoiColumnName = SettingsPageViewModel.Instance.SelectedPoiColumnName; oldBaseMapType = SettingsPageViewModel.Instance.BaseMapType; oldSelectedPoiFilterItem = SettingsPageViewModel.Instance.SelectedPoiFilterItem; oldSelectedPoiFeatureLayer = SettingsPageViewModel.Instance.SelectedPoiFeatureLayer; } } }