2 using System.Collections.Generic;
5 using System.Windows.Navigation;
6 using Microsoft.Phone.Controls;
7 using Windows.Devices.Geolocation;
8 using System.Device.Location;
9 using System.Windows.Shapes;
10 using System.Windows.Media;
11 using Microsoft.Phone.Maps.Controls;
12 using WeatherInformation.Resources;
13 using System.Globalization;
14 using Microsoft.Phone.Maps.Services;
15 using System.Threading.Tasks;
16 using WeatherInformation.Model;
18 namespace WeatherInformation
20 public partial class MapPage : PhoneApplicationPage
22 // TODO anything better than these two instance fields? :(
24 private string _country;
28 InitializeComponent();
31 protected override void OnNavigatedTo(NavigationEventArgs e)
33 // TODO: I am not saving the UI state. If location changed but it was not saved
34 // user will have to pick her location again :(
35 Location locationItem = null;
36 using (var db = new LocationDataContext(LocationDataContext.DBConnectionString))
38 // Define the query to gather all of the to-do items.
39 // var toDoItemsInDB = from Location location in _locationDB.Locations where location.IsSelected select location;
40 locationItem = db.Locations.Where(location => location.IsSelected).FirstOrDefault();
43 if (locationItem != null)
45 GeoCoordinate geoCoordinate = ConvertLocation(locationItem);
47 this.UpdateMap(geoCoordinate, locationItem.City, locationItem.Country);
51 private async Task GetCurrentLocationAndUpdateMap()
53 Geolocator geolocator = new Geolocator();
54 geolocator.DesiredAccuracyInMeters = 50;
56 Geoposition geoposition = await geolocator.GetGeopositionAsync(
57 maximumAge: TimeSpan.FromSeconds(10),
58 timeout: TimeSpan.FromSeconds(10)
60 GeoCoordinate currentGeoCoordinate = CoordinateHelper.ConvertGeocoordinate(geoposition.Coordinate);
62 ReverseGeocodeAndUpdateMap(currentGeoCoordinate);
65 // TODO: problems updating Map because this method may be called when automatically retrieving
66 // the current user's location or when user taps on map tyring to choose by herself her location.
67 // There could be 2 threads updating Map at the same time. Solution: remove the feature
68 // of getting the current user's location (user must always choose her/his location instead of doing
70 private void ReverseGeocodeAndUpdateMap(GeoCoordinate currentGeoCoordinate)
72 ReverseGeocodeQuery currentReverseGeocodeQuery = new ReverseGeocodeQuery();
73 currentReverseGeocodeQuery.GeoCoordinate = currentGeoCoordinate;
74 currentReverseGeocodeQuery.QueryCompleted += QueryCompletedCallback;
75 currentReverseGeocodeQuery.QueryAsync();
78 private void QueryCompletedCallback(object sender, QueryCompletedEventArgs<IList<MapLocation>> eventData)
80 if (eventData.Cancelled)
82 // Be careful!!! If you throw exception from this point your program will finish with "Unhandled Exception".
86 Exception errorException = eventData.Error;
87 if (errorException != null)
90 AppResources.NoticeErrorLocationAutodetection,
91 AppResources.UnavailableAutomaticCurrentLocationMessageBox,
96 if (eventData.Result.Count > 0)
98 MapAddress address = eventData.Result[0].Information.Address;
99 GeoCoordinate currentGeoCoordinate = eventData.Result[0].GeoCoordinate;
101 UpdateMap(currentGeoCoordinate, address.City, address.Country);
106 private void UpdateMap(GeoCoordinate geoCoordinate, string city, string country)
108 // Create a small circle to mark the current location.
109 Ellipse myCircle = new Ellipse();
110 myCircle.Fill = new SolidColorBrush(Colors.Blue);
111 myCircle.Height = 20;
113 myCircle.Opacity = 50;
115 // Create a MapOverlay to contain the circle.
116 MapOverlay myLocationOverlay = new MapOverlay();
117 myLocationOverlay.Content = myCircle;
118 myLocationOverlay.PositionOrigin = new Point(0.5, 0.5);
119 myLocationOverlay.GeoCoordinate = geoCoordinate;
121 // Create a MapLayer to contain the MapOverlay.
122 MapLayer myLocationLayer = new MapLayer();
123 myLocationLayer.Add(myLocationOverlay);
125 this.mapWeatherInformation.Layers.Clear();
127 // TODO: problems? user could press save location and if she is fast enough she
128 // could not realize the location changed.
129 // But well... She will realize later... So.. Is this really a problem?
130 this.mapWeatherInformation.Center = geoCoordinate;
131 this.mapWeatherInformation.ZoomLevel = 13;
133 if (string.IsNullOrEmpty(city))
135 city = AppResources.DefaultCity;
137 if (string.IsNullOrEmpty(country))
139 country = AppResources.DefaultCountry;
141 this.LocationTextCityCountry.Text = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", city, country);
144 // Add the MapLayer to the Map.
145 this.mapWeatherInformation.Layers.Add(myLocationLayer);
148 private static class CoordinateHelper
150 public static GeoCoordinate ConvertGeocoordinate(Geocoordinate geocoordinate)
152 return new GeoCoordinate
154 geocoordinate.Latitude,
155 geocoordinate.Longitude,
156 geocoordinate.Altitude ?? Double.NaN,
157 geocoordinate.Accuracy,
158 geocoordinate.AltitudeAccuracy ?? Double.NaN,
159 geocoordinate.Speed ?? Double.NaN,
160 geocoordinate.Heading ?? Double.NaN
165 // TODO: check data before storing :(
166 // http://stackoverflow.com/questions/4521435/what-specific-values-can-a-c-sharp-double-represent-that-a-sql-server-float-can
167 private void StoreLocation(GeoCoordinate geocoordinate)
169 Location locationItem = null;
170 using (var db = new LocationDataContext(LocationDataContext.DBConnectionString))
172 // Define the query to gather all of the to-do items.
173 // var toDoItemsInDB = from Location location in _locationDB.Locations where location.IsSelected select location;
174 locationItem = db.Locations.Where(location => location.IsSelected).FirstOrDefault();
176 if (locationItem != null)
178 locationItem.Latitude = geocoordinate.Latitude;
179 locationItem.Longitude = geocoordinate.Longitude;
180 locationItem.Altitude = geocoordinate.Altitude;
181 locationItem.City = _city ?? "";
182 locationItem.Country = _country ?? "";
183 locationItem.HorizontalAccuracy = geocoordinate.HorizontalAccuracy;
184 locationItem.VerticalAccuracy = geocoordinate.VerticalAccuracy;
185 locationItem.Speed = geocoordinate.Speed;
186 locationItem.Course = geocoordinate.Course;
187 locationItem.IsSelected = true;
188 locationItem.LastRemoteDataUpdate = null;
192 locationItem = new Location()
194 Latitude = geocoordinate.Latitude,
195 Longitude = geocoordinate.Longitude,
196 Altitude = geocoordinate.Altitude,
198 Country = _country ?? "",
199 HorizontalAccuracy = geocoordinate.HorizontalAccuracy,
200 VerticalAccuracy = geocoordinate.VerticalAccuracy,
201 Speed = geocoordinate.Speed,
202 Course = geocoordinate.Course,
204 LastRemoteDataUpdate = null,
207 // Add a location item to the local database.
208 db.Locations.InsertOnSubmit(locationItem);
215 private GeoCoordinate ConvertLocation(Location locationItem)
217 return new GeoCoordinate
219 locationItem.Latitude,
220 locationItem.Longitude,
221 locationItem.Altitude,
222 locationItem.HorizontalAccuracy,
223 locationItem.VerticalAccuracy,
229 private void mapWeatherInformation_Tap(object sender, System.Windows.Input.GestureEventArgs e)
231 var point = e.GetPosition(this.mapWeatherInformation);
232 GeoCoordinate geocoordinate = this.mapWeatherInformation.ConvertViewportPointToGeoCoordinate(point);
233 ReverseGeocodeAndUpdateMap(geocoordinate);
236 private async void GetCurrentLocationButton_Click(object sender, RoutedEventArgs e)
240 await this.GetCurrentLocationAndUpdateMap();
244 // TODO: make sure when exception in GetCurrentLocationAndUpdateMap we catch it here.
246 AppResources.NoticeErrorLocationAutodetection,
247 AppResources.UnavailableAutomaticCurrentLocationMessageBox,
248 MessageBoxButton.OK);
252 private void SaveLocationButton_Click(object sender, RoutedEventArgs e)
254 // TODO: Could there some problem if user clicks button and thread is in this very moment updating map?
255 var geoCoordinate = this.mapWeatherInformation.Center;
257 StoreLocation(geoCoordinate);
260 private void ZoomOutButton_Click(object sender, RoutedEventArgs e)
262 this.mapWeatherInformation.ZoomLevel = this.mapWeatherInformation.ZoomLevel - 1;
265 private void ZoomInButton_Click(object sender, RoutedEventArgs e)
267 this.mapWeatherInformation.ZoomLevel = this.mapWeatherInformation.ZoomLevel + 1;