4 using System.Windows.Navigation;
5 using Microsoft.Phone.Controls;
6 using Windows.Devices.Geolocation;
7 using System.Device.Location;
8 using System.Windows.Shapes;
9 using System.Windows.Media;
10 using Microsoft.Phone.Maps.Controls;
11 using System.Threading.Tasks;
12 using WeatherInformation.Model;
14 namespace WeatherInformation
16 public partial class MapPage : PhoneApplicationPage, ReverseGeoCode.IReverseGeoCode
18 private bool _isNewPageInstance;
19 private ReverseGeoCode _reverseGeoCodeOnProgress;
20 // TODO: how big is a MapLayer object?
21 private MapOverlay _locationOverlay;
25 InitializeComponent();
27 _isNewPageInstance = true;
30 protected override void OnNavigatedTo(NavigationEventArgs e)
32 var geolocator = new Geolocator();
33 if (geolocator.LocationStatus != PositionStatus.Ready)
35 GetCurrentLocationButton.IsEnabled = false;
38 GeoCoordinate restoreReverseOnProgress = null;
39 Location restoreLocation = null;
40 if (_isNewPageInstance)
44 restoreReverseOnProgress = (GeoCoordinate)State["ReverseGeoCoorDinateOnProgress"];
45 restoreLocation = (Location)State["CurrentChosenMapLocation"];
48 // Set _isNewPageInstance to false. If the user navigates back to this page
49 // and it has remained in memory, this value will continue to be false.
50 _isNewPageInstance = false;
53 if (restoreLocation != null)
55 location = restoreLocation;
57 else if (_locationOverlay != null)
59 location = CoordinateHelper.GeoCoordinateToLocation(
60 _locationOverlay.GeoCoordinate,
61 LocationTextCity.Text,
62 LocationTextCountry.Text);
66 using (var db = new LocationDataContext(LocationDataContext.DBConnectionString))
68 // Define the query to gather all of the to-do items.
69 // var toDoItemsInDB = from Location location in _locationDB.Locations where location.IsSelected select location;
70 location = db.Locations.Where(locationItem => locationItem.IsSelected).FirstOrDefault();
77 UpdateMap(CoordinateHelper.LocationToGeoCoordinate(location),
78 location.City, location.Country);
81 if (restoreReverseOnProgress != null)
84 ReverseGeocodeAndUpdateMap(restoreReverseOnProgress);
92 protected override void OnNavigatedFrom(NavigationEventArgs e)
94 if (e.NavigationMode != System.Windows.Navigation.NavigationMode.Back)
96 // TODO: Could Center be null?
97 State["CurrentChosenMapLocation"] = CoordinateHelper.GeoCoordinateToLocation(
98 mapWeatherInformation.Center,
99 LocationTextCity.Text,
100 LocationTextCountry.Text);
102 if (_reverseGeoCodeOnProgress != null)
104 State["ReverseGeoCoorDinateOnProgress"] = _reverseGeoCodeOnProgress.CoorDinate;
109 public void OnCompletedReverseGeoCode(GeoCoordinate geoCoordinate, string city, string country)
111 UpdateMap(geoCoordinate, city, country);
113 _reverseGeoCodeOnProgress = null;
116 private async Task GetCurrentLocationAndUpdateMap()
118 var geolocator = new Geolocator();
119 geolocator.DesiredAccuracyInMeters = 50;
120 geolocator.ReportInterval = 1000;
122 var geoposition = await geolocator.GetGeopositionAsync(
123 maximumAge: TimeSpan.FromSeconds(1),
124 timeout: TimeSpan.FromSeconds(10)
126 // TODO: check if the following is true:
127 // Without ConfigureAwait(false) await returns data on the calling thread. (AFAIK for this Context)
128 // otherwise I should call: Dispatcher.BeginInvoke(() => ReverseGeocodeAndUpdateMap(currentGeoCoordinate));
130 // TODO: What is going to happend when Timeout? Exception or geposition will be null value.
131 // Should I check for null value in case of Timeout?
132 var currentGeoCoordinate = CoordinateHelper.ConvertGeocoordinate(geoposition.Coordinate);
134 ReverseGeocodeAndUpdateMap(currentGeoCoordinate);
137 private void ReverseGeocodeAndUpdateMap(GeoCoordinate geoCoordinate)
139 var reverseGeoCode = new ReverseGeoCode()
142 CoorDinate = geoCoordinate
145 if (_reverseGeoCodeOnProgress != null)
147 // GC may release old object.
148 _reverseGeoCodeOnProgress.Page = null;
151 _reverseGeoCodeOnProgress = reverseGeoCode;
152 _reverseGeoCodeOnProgress.DoReverseGeocode(geoCoordinate);
155 private void UpdateMap(GeoCoordinate geoCoordinate, string city, string country)
157 // Create a small circle to mark the current location.
158 Ellipse myCircle = new Ellipse();
159 myCircle.Fill = new SolidColorBrush(Colors.Blue);
160 myCircle.Height = 20;
162 myCircle.Opacity = 50;
164 // Create a MapOverlay to contain the circle.
165 _locationOverlay = new MapOverlay();
166 _locationOverlay.Content = myCircle;
167 _locationOverlay.PositionOrigin = new Point(0.5, 0.5);
168 _locationOverlay.GeoCoordinate = geoCoordinate;
170 // Create a MapLayer to contain the MapOverlay.
171 MapLayer myLocationLayer = new MapLayer();
172 myLocationLayer.Add(_locationOverlay);
174 mapWeatherInformation.Layers.Clear();
176 // TODO: problems? user could press save location and if she is fast enough she
177 // could not realize the location changed.
178 // But well... She will realize later... So.. Is this really a problem?
179 mapWeatherInformation.Center = geoCoordinate;
180 mapWeatherInformation.ZoomLevel = 13;
182 LocationTextCity.Text = city;
183 LocationTextCountry.Text = country;
184 // Add the MapLayer to the Map.
185 mapWeatherInformation.Layers.Add(myLocationLayer);
188 private static class CoordinateHelper
190 public static GeoCoordinate ConvertGeocoordinate(Geocoordinate geocoordinate)
192 return new GeoCoordinate
194 geocoordinate.Latitude,
195 geocoordinate.Longitude,
196 geocoordinate.Altitude ?? Double.NaN,
197 geocoordinate.Accuracy,
198 geocoordinate.AltitudeAccuracy ?? Double.NaN,
199 geocoordinate.Speed ?? Double.NaN,
200 geocoordinate.Heading ?? Double.NaN
204 public static GeoCoordinate LocationToGeoCoordinate(Location locationItem)
206 return new GeoCoordinate
208 locationItem.Latitude,
209 locationItem.Longitude,
210 locationItem.Altitude,
211 locationItem.HorizontalAccuracy,
212 locationItem.VerticalAccuracy,
218 public static Location GeoCoordinateToLocation(GeoCoordinate geoCoordinate, string city, string country)
220 return new Location()
222 Latitude = geoCoordinate.Latitude,
223 Longitude = geoCoordinate.Longitude,
224 Altitude = geoCoordinate.Altitude,
227 HorizontalAccuracy = geoCoordinate.HorizontalAccuracy,
228 VerticalAccuracy = geoCoordinate.VerticalAccuracy,
229 Speed = geoCoordinate.Speed,
230 Course = geoCoordinate.Course,
232 LastRemoteDataUpdate = null,
237 // TODO: check data before storing :(
238 // http://stackoverflow.com/questions/4521435/what-specific-values-can-a-c-sharp-double-represent-that-a-sql-server-float-can
239 private void StoreLocation(GeoCoordinate geocoordinate, string city, string country)
241 Location locationItem = null;
242 using (var db = new LocationDataContext(LocationDataContext.DBConnectionString))
244 // Define the query to gather all of the to-do items.
245 // var toDoItemsInDB = from Location location in _locationDB.Locations where location.IsSelected select location;
246 locationItem = db.Locations.Where(location => location.IsSelected).FirstOrDefault();
248 if (locationItem != null)
250 locationItem.Latitude = geocoordinate.Latitude;
251 locationItem.Longitude = geocoordinate.Longitude;
252 locationItem.Altitude = geocoordinate.Altitude;
253 locationItem.City = city;
254 locationItem.Country = country;
255 locationItem.HorizontalAccuracy = geocoordinate.HorizontalAccuracy;
256 locationItem.VerticalAccuracy = geocoordinate.VerticalAccuracy;
257 locationItem.Speed = geocoordinate.Speed;
258 locationItem.Course = geocoordinate.Course;
259 locationItem.IsSelected = true;
260 locationItem.LastRemoteDataUpdate = null;
264 locationItem = new Location()
266 Latitude = geocoordinate.Latitude,
267 Longitude = geocoordinate.Longitude,
268 Altitude = geocoordinate.Altitude,
271 HorizontalAccuracy = geocoordinate.HorizontalAccuracy,
272 VerticalAccuracy = geocoordinate.VerticalAccuracy,
273 Speed = geocoordinate.Speed,
274 Course = geocoordinate.Course,
276 LastRemoteDataUpdate = null,
279 // Add a location item to the local database.
280 db.Locations.InsertOnSubmit(locationItem);
287 private void mapWeatherInformation_Tap(object sender, System.Windows.Input.GestureEventArgs e)
289 // TODO: if exception from here application will crash (I guess)
290 var point = e.GetPosition(this.mapWeatherInformation);
291 GeoCoordinate geocoordinate = this.mapWeatherInformation.ConvertViewportPointToGeoCoordinate(point);
293 ReverseGeocodeAndUpdateMap(geocoordinate);
296 private async void GetCurrentLocationButton_Click(object sender, RoutedEventArgs e)
298 //Geolocator geolocator = new Geolocator();
299 //geolocator.DesiredAccuracyInMeters = 50;
300 //if (geolocator.LocationStatus != PositionStatus.Ready)
302 // // TODO: to use ToastPrompt from the Coding4Fun Toolkit (using NuGet)
306 // TODO: if exception from here application will crash (I guess)
307 await this.GetCurrentLocationAndUpdateMap();
310 private void SaveLocationButton_Click(object sender, RoutedEventArgs e)
312 // TODO: Could Center be null?
313 StoreLocation(this.mapWeatherInformation.Center, this.LocationTextCity.Text, this.LocationTextCountry.Text);
316 private void ShowProgressBar()
318 GetCurrentLocationButton.IsEnabled = false;
319 GetCurrentLocationButton.Visibility = Visibility.Collapsed;
320 SaveLocationButton.IsEnabled = false;
321 SaveLocationButton.Visibility = Visibility.Collapsed;
322 ProgressBarRemoteData.IsEnabled = true;
323 ProgressBarRemoteData.Visibility = Visibility.Visible;
326 private void RemoveProgressBar()
328 GetCurrentLocationButton.IsEnabled = true;
329 GetCurrentLocationButton.Visibility = Visibility.Visible;
330 SaveLocationButton.IsEnabled = true;
331 SaveLocationButton.Visibility = Visibility.Visible;
332 ProgressBarRemoteData.IsEnabled = false;
333 ProgressBarRemoteData.Visibility = Visibility.Collapsed;
338 private void ZoomOutButton_Click(object sender, RoutedEventArgs e)
340 this.mapWeatherInformation.ZoomLevel = this.mapWeatherInformation.ZoomLevel - 1;
343 private void ZoomInButton_Click(object sender, RoutedEventArgs e)
345 this.mapWeatherInformation.ZoomLevel = this.mapWeatherInformation.ZoomLevel + 1;