WeatherInformation WP8: trying to to work with database
authorgu.martinm@gmail.com <gu.martinm@gmail.com>
Sun, 10 Aug 2014 23:12:04 +0000 (01:12 +0200)
committergu.martinm@gmail.com <gu.martinm@gmail.com>
Sun, 10 Aug 2014 23:12:04 +0000 (01:12 +0200)
17 files changed:
WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml
WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/Model/Location.cs [new file with mode: 0644]
WindowsPhone/WeatherInformation/WeatherInformation/Model/LocationDataContext.cs [new file with mode: 0644]
WindowsPhone/WeatherInformation/WeatherInformation/Model/Services/StoredLocation.cs [deleted file]
WindowsPhone/WeatherInformation/WeatherInformation/Model/WeatherData.cs
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.Designer.cs
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.es.resx
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.es.xlf
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.qps-ploc.xlf
WindowsPhone/WeatherInformation/WeatherInformation/Resources/AppResources.resx
WindowsPhone/WeatherInformation/WeatherInformation/SelectedDatePage.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/ViewModels/MainViewModel.cs
WindowsPhone/WeatherInformation/WeatherInformation/ViewModels/SelectedDateViewModel.cs
WindowsPhone/WeatherInformation/WeatherInformation/WeatherInformation.csproj

index 53ccf9b..0d1fb52 100644 (file)
@@ -81,6 +81,16 @@ namespace WeatherInformation
             // Inicialización del idioma
             InitializeLanguage();
 
+            // Create the database if it does not exist.
+            using (LocationDataContext db = new LocationDataContext(LocationDataContext.DBConnectionString))
+            {
+                if (db.DatabaseExists() == false)
+                {
+                    //Create the database
+                    db.CreateDatabase();
+                }
+            }
+
             // Mostrar información de generación de perfiles gráfica durante la depuración.
             if (Debugger.IsAttached)
             {
@@ -102,143 +112,6 @@ namespace WeatherInformation
             }
         }
 
-        public void GetDataAsync()
-        {
-            // Call the GetData method on a new thread.
-            // TODO: Are there too many threads? HttpClient is going to create more... (threadpools and stuff like that...)
-            Thread t = new Thread(new ThreadStart(GetData));
-            t.Start();
-        }
-
-        async private void GetData()
-        {
-            // Check to see if data exists in isolated storage and see if the data is fresh.
-            WeatherData weatherData = GetIsolatedStoredData();
-
-            if ((weatherData != null) && IsStoredDataFresh() && !StoredLocation.IsNewLocation)
-            {
-                ApplicationDataObject = weatherData;
-            }
-            else
-            {
-                // Otherwise, it gets the data from the web.
-                ApplicationDataObject = await LoadDataAsync();
-            }
-        }
-
-        private bool IsStoredDataFresh()
-        {
-            // Check to see if the data is fresh.
-            // This example uses 30 seconds as the valid time window to make it easy to test. 
-            // Real apps will use a larger window.
-
-            // Check the time elapsed since data was last saved to isolated storage.
-            TimeSpan TimeSinceLastSave = TimeSpan.FromSeconds(0);
-            if (IsolatedStorageSettings.ApplicationSettings.Contains("DataLastSavedTime"))
-            {
-                DateTime dataLastSaveTime = (DateTime)IsolatedStorageSettings.ApplicationSettings["DataLastSavedTime"];
-                TimeSinceLastSave = DateTime.Now - dataLastSaveTime;
-            }
-            
-            if (TimeSinceLastSave.TotalSeconds < 30)
-            {
-                return true;
-            }
-
-            return false;
-        }
-
-        private WeatherData GetIsolatedStoredData()
-        {
-            string JSONRemoteCurrentWeather = null;
-            string JSONRemoteForecastWeather = null;
-
-            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
-            {
-                if (isoStore.FileExists("JSONRemoteCurrentWeatherFile.txt") &&
-                    isoStore.FileExists("JSONRemoteForecastWeatherFile.txt"))
-                {
-                    using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open))
-                    using (StreamReader sr = new StreamReader(file))
-                    {
-                        // This method loads the data from isolated storage, if it is available.
-                        JSONRemoteCurrentWeather = sr.ReadLine();
-                    }
-
-                    using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open))
-                    using (StreamReader sr = new StreamReader(file))
-                    {
-                        // This method loads the data from isolated storage, if it is available.
-                        JSONRemoteForecastWeather = sr.ReadLine();
-                    }
-                }
-            }
-
-            if (!string.IsNullOrEmpty(JSONRemoteCurrentWeather) && !string.IsNullOrEmpty(JSONRemoteForecastWeather))
-            {
-                return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
-            }
-
-            return null;
-        }
-
-        /// <summary>
-        /// Retrieve remote weather data.
-        /// </summary>
-        async public Task<WeatherData> LoadDataAsync()
-        {
-            double latitude = StoredLocation.CurrentLatitude;
-            double longitude = StoredLocation.CurrentLongitude;
-            int resultsNumber = Convert.ToInt32(AppResources.APIOpenWeatherMapResultsNumber);
-
-            CustomHTTPClient httpClient = new CustomHTTPClient();
-
-            string formattedForecastURL = String.Format(
-                CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapForecast,
-                AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber);
-            string JSONRemoteForecastWeather = await httpClient.GetWeatherDataAsync(formattedForecastURL);
-
-            string formattedCurrentURL = String.Format(
-                CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapCurrent,
-                AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber);
-            string JSONRemoteCurrentWeather = await httpClient.GetWeatherDataAsync(formattedCurrentURL);
-
-            return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
-        }
-
-        private ForecastWeather ForecastWeatherParser(string remoteForecastWeatherData)
-        {
-            ServiceParser parser = new ServiceParser(new JsonParser());
-            return parser.GetForecastWeather(remoteForecastWeatherData);
-        }
-
-        private CurrentWeather CurrentWeatherParser(string remoteCurrentWeatherData)
-        {
-            ServiceParser parser = new ServiceParser(new JsonParser());
-            return parser.GetCurrentWeather(remoteCurrentWeatherData);
-        }
-
-        private WeatherData WeatherDataParser(string JSONRemoteForecastWeather, string JSONRemoteCurrentWeather)
-        {
-            if (string.IsNullOrEmpty(JSONRemoteForecastWeather))
-            {
-                throw new ArgumentException("Missing argument", "JSONRemoteForecastWeather"); 
-            }
-            if (string.IsNullOrEmpty(JSONRemoteCurrentWeather))
-            {
-                throw new ArgumentException("Missing argument", "JSONRemoteCurrentWeather");
-            }
-
-            return new WeatherData
-            {
-                JSONRemoteCurrent = JSONRemoteCurrentWeather,
-                JSONRemoteForecast = JSONRemoteForecastWeather,
-                RemoteCurrent = CurrentWeatherParser(JSONRemoteCurrentWeather),
-                RemoteForecast = ForecastWeatherParser(JSONRemoteForecastWeather),
-                WasThereRemoteError = false
-            };
-        }
-
         // no way of moving temporary file atomically with IsolatedStorageFile. LINUX OWNS MICROSOFT.
         private void SaveDataToIsolatedStorage(string fileName, string value)
         {
index 9f244f5..a7e3d63 100644 (file)
@@ -1,5 +1,6 @@
 using Microsoft.Phone.Controls;
 using System;
+using System.Linq;
 using System.Globalization;
 using System.IO.IsolatedStorage;
 using System.Windows;
@@ -9,6 +10,11 @@ using WeatherInformation.Model;
 using WeatherInformation.Model.Services;
 using WeatherInformation.Resources;
 using WeatherInformation.ViewModels;
+using System.Threading;
+using System.Threading.Tasks;
+using WeatherInformation.Model.ForecastWeatherParser;
+using WeatherInformation.Model.CurrentWeatherParser;
+using WeatherInformation.Model.JsonDataParser;
 
 namespace WeatherInformation
 {
@@ -16,6 +22,9 @@ namespace WeatherInformation
     {
         private MainViewModel _mainViewModel;
         private bool _isNewPageInstance = false;
+        // Data context for the local database
+        private LocationDataContext _locationDB;
+        private Location _locationItem;
 
         // Constructor
         public MainPage()
@@ -32,7 +41,10 @@ namespace WeatherInformation
             (Application.Current as WeatherInformation.App).ApplicationDataObjectChanged +=
                           new EventHandler(MainPage_ApplicationDataObjectChanged);
 
+            // Connect to the database and instantiate data context.
+            _locationDB = new LocationDataContext(LocationDataContext.DBConnectionString);
 
+            _locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault();
             // Código de ejemplo para traducir ApplicationBar
             //BuildLocalizedApplicationBar();
         }
@@ -61,23 +73,37 @@ namespace WeatherInformation
             UpdateApplicationDataUI();
         }
 
+        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
+        {
+            // Call the base method.
+            base.OnNavigatedFrom(e);
+
+            // Save changes to the database.
+            _locationDB.SubmitChanges();
+
+            // No calling _locationDB.Dispose? :/
+        }
+
         private void UpdateApplicationDataUI()
         {
-            if (StoredLocation.IsThereCurrentLocation)
+            if (_locationItem == null)
             {
-                // If the application member variable is not empty,
-                // set the page's data object from the application member variable.
-                // TODO: I am setting and getting ApplicationDataObject from different threads!!!! What if I do not see its last value? Do I need synchronization? :/
-                WeatherData weatherData = (Application.Current as WeatherInformation.App).ApplicationDataObject;
-                if (weatherData != null && !StoredLocation.IsNewLocation)
-                {
-                    UpdateUI();
-                }
-                else
-                {
-                    // Otherwise, call the method that loads data.
-                    (Application.Current as WeatherInformation.App).GetDataAsync();
-                }
+                // Nothing to do.
+                return;
+            }
+
+            // If the application member variable is not empty,
+            // set the page's data object from the application member variable.
+            // TODO: I am setting and getting ApplicationDataObject from different threads!!!! What if I do not see its last value? Do I need synchronization? :/
+            WeatherData weatherData = (Application.Current as WeatherInformation.App).ApplicationDataObject;
+            if (weatherData != null && !_locationItem.IsNewLocation && IsStoredDataFresh())
+            {
+                UpdateUI();
+            }
+            else
+            {
+                // Otherwise, call the method that loads data.
+                GetDataAsync();
             }
         }
 
@@ -99,14 +125,18 @@ namespace WeatherInformation
                 {
                     MessageBox.Show(
                          AppResources.NoticeThereIsNotCurrentLocation,
-                         AppResources.AskForLocationConsentMessageBoxCaption,
+                         AppResources.UnavailableAutomaticCurrentLocationMessageBox,
                          MessageBoxButton.OK);
                     return;
                 }
 
                 _mainViewModel.LoadData(weatherData);
 
-                StoredLocation.IsNewLocation = false;
+                var locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault();
+                if (locationItem != null)
+                {
+                    locationItem.IsNewLocation = false;
+                }           
             }
         }
 
@@ -121,6 +151,140 @@ namespace WeatherInformation
             NavigationService.Navigate(new Uri(uri, UriKind.Relative));
         }
 
+        public void GetDataAsync()
+        {
+            // Call the GetData method on a new thread.
+            // TODO: Are there too many threads? HttpClient is going to create more... (threadpools and stuff like that...)
+            Thread t = new Thread(new ThreadStart(GetData));
+            t.Start();
+        }
+
+        async private void GetData()
+        {
+            // Check to see if data exists in storage and see if the data is fresh.
+            WeatherData weatherData = GetIsolatedStoredData();
+
+            if ((weatherData != null) && IsStoredDataFresh() && !_locationItem.IsNewLocation)
+            {
+                (Application.Current as WeatherInformation.App).ApplicationDataObject = weatherData;
+            }
+            else
+            {
+                // Otherwise, it gets the data from the web.
+                (Application.Current as WeatherInformation.App).ApplicationDataObject = await LoadDataAsync();
+            }
+        }
+
+        /// <summary>
+        /// Retrieve remote weather data.
+        /// </summary>
+        async public Task<WeatherData> LoadDataAsync()
+        {
+            double latitude = _locationItem.Latitude;
+            double longitude = _locationItem.Longitude;
+            int resultsNumber = Convert.ToInt32(AppResources.APIOpenWeatherMapResultsNumber);
+
+            CustomHTTPClient httpClient = new CustomHTTPClient();
+
+            string formattedForecastURL = String.Format(
+                CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapForecast,
+                AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber);
+            string JSONRemoteForecastWeather = await httpClient.GetWeatherDataAsync(formattedForecastURL);
+
+            string formattedCurrentURL = String.Format(
+                CultureInfo.InvariantCulture, AppResources.URIAPIOpenWeatherMapCurrent,
+                AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber);
+            string JSONRemoteCurrentWeather = await httpClient.GetWeatherDataAsync(formattedCurrentURL);
+
+            return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
+        }
+
+        // ESTE METODO ERA PARA CARGAR LOS DATOS JSON NO LOS DE LA BASE DE DATOS. HAY QUE REPENSAR ESTO :(
+        private bool IsStoredDataFresh()
+        {
+            // Check to see if the data is fresh.
+            // This example uses 30 seconds as the valid time window to make it easy to test. 
+            // Real apps will use a larger window.
+
+            // Check the time elapsed since data was last saved to storage.
+            DateTime dataLastSaveTime = _locationItem.StoredTime;
+            TimeSpan timeSinceLastSave = DateTime.Now - dataLastSaveTime;
+
+            if (timeSinceLastSave.TotalSeconds < 30)
+            {
+                return true;
+            }
+
+            return false;
+        }
+
+        private WeatherData GetIsolatedStoredData()
+        {
+            string JSONRemoteCurrentWeather = null;
+            string JSONRemoteForecastWeather = null;
+
+            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
+            {
+                if (isoStore.FileExists("JSONRemoteCurrentWeatherFile.txt") &&
+                    isoStore.FileExists("JSONRemoteForecastWeatherFile.txt"))
+                {
+                    using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open))
+                    using (StreamReader sr = new StreamReader(file))
+                    {
+                        // This method loads the data from isolated storage, if it is available.
+                        JSONRemoteCurrentWeather = sr.ReadLine();
+                    }
+
+                    using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open))
+                    using (StreamReader sr = new StreamReader(file))
+                    {
+                        // This method loads the data from isolated storage, if it is available.
+                        JSONRemoteForecastWeather = sr.ReadLine();
+                    }
+                }
+            }
+
+            if (!string.IsNullOrEmpty(JSONRemoteCurrentWeather) && !string.IsNullOrEmpty(JSONRemoteForecastWeather))
+            {
+                return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
+            }
+
+            return null;
+        }
+
+        private ForecastWeather ForecastWeatherParser(string remoteForecastWeatherData)
+        {
+            ServiceParser parser = new ServiceParser(new JsonParser());
+            return parser.GetForecastWeather(remoteForecastWeatherData);
+        }
+
+        private CurrentWeather CurrentWeatherParser(string remoteCurrentWeatherData)
+        {
+            ServiceParser parser = new ServiceParser(new JsonParser());
+            return parser.GetCurrentWeather(remoteCurrentWeatherData);
+        }
+
+        private WeatherData WeatherDataParser(string JSONRemoteForecastWeather, string JSONRemoteCurrentWeather)
+        {
+            if (string.IsNullOrEmpty(JSONRemoteForecastWeather))
+            {
+                throw new ArgumentException("Missing argument", "JSONRemoteForecastWeather");
+            }
+            if (string.IsNullOrEmpty(JSONRemoteCurrentWeather))
+            {
+                throw new ArgumentException("Missing argument", "JSONRemoteCurrentWeather");
+            }
+
+            return new WeatherData
+            {
+                JSONRemoteCurrent = JSONRemoteCurrentWeather,
+                JSONRemoteForecast = JSONRemoteForecastWeather,
+                RemoteCurrent = CurrentWeatherParser(JSONRemoteCurrentWeather),
+                RemoteForecast = ForecastWeatherParser(JSONRemoteForecastWeather),
+                WasThereRemoteError = false
+            };
+        }
+
         private void Location_Click(object sender, EventArgs e)
         {
             NavigationService.Navigate(new Uri("/MapPage.xaml", UriKind.Relative));
index 2aec0e7..5c4bd37 100644 (file)
@@ -20,6 +20,7 @@
             <RowDefinition Height="Auto"/>
             <RowDefinition/>
             <RowDefinition Height="Auto"/>
+            <RowDefinition Height="Auto"/>
         </Grid.RowDefinitions>
 
         <!--TitlePanel contiene el nombre de la aplicación y el título de la página-->
         <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
             <maps:Map x:Name="mapWeatherInformation" Grid.Row="1" Tap="mapWeatherInformation_Tap"/>
         </Grid>
-        <Button x:Name="SaveLocationButton" Grid.Row="2" Content="{Binding LocalizedResources.MapPageSaveLocationButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}" HorizontalAlignment="Center"  VerticalAlignment="Bottom" Click="SaveLocationButton_Click"/>
+        <Grid Grid.Row="2">
+            <Button x:Name="SaveLocationButton"  Content="{Binding LocalizedResources.MapPageSaveLocationButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}" Click="SaveLocationButton_Click" HorizontalAlignment="Left" VerticalAlignment="Center"/>
+            <Button x:Name="GetCurrentLocationButton" HorizontalAlignment="Right" VerticalAlignment="Center" Content="{Binding LocalizedResources.MapPageGetCurrentLocationButton, Mode=OneWay, Source={StaticResource LocalizedStrings}}" Click="GetCurrentLocationButton_Click"/>
+        </Grid>
+        <Grid Grid.Row="3">
+            <Button x:Name="ZoomInButton" Click="ZoomInButton_Click" HorizontalAlignment="Left" VerticalAlignment="Center" Content="Zoom +"/>
+            <Button x:Name="ZoomOutButton" Click="ZoomOutButton_Click" HorizontalAlignment="Right" VerticalAlignment="Center" Content="Zoom -"/>
+        </Grid>
     </Grid>
 
 </phone:PhoneApplicationPage>
\ No newline at end of file
index 0162259..b6320db 100644 (file)
@@ -17,96 +17,61 @@ using WeatherInformation.Resources;
 using System.Globalization;
 using Microsoft.Phone.Maps.Services;
 using WeatherInformation.Model.Services;
+using System.Threading.Tasks;
+using WeatherInformation.Model;
 
 namespace WeatherInformation
 {
     public partial class MapPage : PhoneApplicationPage
     {
-        // Settings
-        private readonly IsolatedStorageSettings _settings;
+        // Data context for the local database
+        private LocationDataContext _locationDB;
 
         public MapPage()
         {
             InitializeComponent();
 
-            // Get the _settings for this application.
-            _settings = IsolatedStorageSettings.ApplicationSettings;
+            // Connect to the database and instantiate data context.
+            _locationDB = new LocationDataContext(LocationDataContext.DBConnectionString);
         }
 
         protected override void OnNavigatedTo(NavigationEventArgs e)
         {
-            if (!_settings.Contains("LocationConsent"))
+            
+            // Define the query to gather all of the to-do items.
+            // var toDoItemsInDB = from Location location in _locationDB.Locations where location.IsSelected select location;
+            var locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault();
+            if (locationItem != null)
             {
-                MessageBoxResult result = MessageBox.Show(
-                    AppResources.AskForLocationConsentMessageBox,
-                    AppResources.AskForLocationConsentMessageBoxCaption,
-                    MessageBoxButton.OKCancel);
+                GeoCoordinate geoCoordinate = ConvertLocation(locationItem);
 
-                if (result == MessageBoxResult.OK)
-                {
-                    _settings["LocationConsent"] = true;
-                }
-                else
-                {
-                    _settings["LocationConsent"] = false;
-                }
-
-                _settings.Save();
+                this.UpdateMap(geoCoordinate, locationItem.City, locationItem.Country);
             }
+        }
 
-            if ((bool)_settings["LocationConsent"] != true)
-            {
-                // The user has opted out of Location.
-                return;
-            }
+        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
+        {
+            // Call the base method.
+            base.OnNavigatedFrom(e);
 
-            if (!StoredLocation.IsThereCurrentLocation)
-            {
-                this.GetLocation();
-            }
-            else
-            {
-                GeoCoordinate geoCoordinate = CoordinateHelper.GetStoredGeoCoordinate();
+            // Save changes to the database.
+            _locationDB.SubmitChanges();
 
-                this.UpdateMap(geoCoordinate, StoredLocation.City, StoredLocation.Country);
-            }
+            // No calling _locationDB.Dispose? :/
         }
 
-        private async void GetLocation()
+        private async Task GetCurrentLocationAndUpdateMap()
         {
             Geolocator geolocator = new Geolocator();
             geolocator.DesiredAccuracyInMeters = 50;
 
-            try
-            {
-                Geoposition geoposition = await geolocator.GetGeopositionAsync(
-                    maximumAge: TimeSpan.FromMinutes(5),
-                    timeout: TimeSpan.FromSeconds(10)
-                    );
-                GeoCoordinate currentGeoCoordinate = CoordinateHelper.ConvertGeocoordinate(geoposition.Coordinate);
-
-                ReverseGeocodeAndUpdateMap(currentGeoCoordinate);
-            }
-            catch (Exception ex)
-            {
-                if ((uint)ex.HResult == 0x80004004)
-                {
+            Geoposition geoposition = await geolocator.GetGeopositionAsync(
+                maximumAge: TimeSpan.FromMinutes(5),
+                timeout: TimeSpan.FromSeconds(10)
+                );
+            GeoCoordinate currentGeoCoordinate = CoordinateHelper.ConvertGeocoordinate(geoposition.Coordinate);
 
-                    // the application does not have the right capability or the location master switch is off
-                    MessageBox.Show(
-                        AppResources.NoticeErrorLocationAutodetection,
-                        AppResources.AskForLocationConsentMessageBoxCaption,
-                        MessageBoxButton.OK);
-                }
-                else
-                {
-                    // something else happened acquring the location
-                    MessageBox.Show(
-                        AppResources.NoticeErrorLocationAutodetection,
-                        AppResources.AskForLocationConsentMessageBoxCaption,
-                        MessageBoxButton.OK);
-                }
-            }
+            ReverseGeocodeAndUpdateMap(currentGeoCoordinate);
         }
 
         // TODO: problems updating Map because this method may be called when automatically retrieving
@@ -133,8 +98,10 @@ namespace WeatherInformation
             Exception errorException = eventData.Error;
             if (errorException != null)
             {
-                // TODO: Show some log. I need to use remote logging :(
-                return;
+                MessageBox.Show(
+                    AppResources.NoticeErrorLocationAutodetection,
+                    AppResources.UnavailableAutomaticCurrentLocationMessageBox,
+                    MessageBoxButton.OK);
             }
             else
             {
@@ -195,43 +162,84 @@ namespace WeatherInformation
                     geocoordinate.Heading ?? Double.NaN
                     );
             }
+        }
 
-            // TODO: database
-            // TODO: What if Double.NAN or null... Am I going to have some problem storing data in IsolatedStorageSettings?
-            public static void StoreGeoCoordinate(GeoCoordinate geocoordinate)
+        // TODO: check data before storing :(
+        // http://stackoverflow.com/questions/4521435/what-specific-values-can-a-c-sharp-double-represent-that-a-sql-server-float-can
+        private void StoreLocation(GeoCoordinate geocoordinate)
+        {
+            var locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault();
+            if (locationItem != null)
             {
-                StoredLocation.CurrentLatitude = geocoordinate.Latitude;
-                StoredLocation.CurrentLongitude = geocoordinate.Longitude;
-                StoredLocation.IsNewLocation = true;
-                StoredLocation.CurrentAltitude = geocoordinate.Altitude;
-                StoredLocation.CurrentHorizontalAccuracy = geocoordinate.HorizontalAccuracy;
-                StoredLocation.CurrentVerticalAccuracy = geocoordinate.VerticalAccuracy;
-                StoredLocation.CurrentSpeed = geocoordinate.Speed;
-                StoredLocation.CurrentCourse = geocoordinate.Course;
+                locationItem.Latitude = geocoordinate.Latitude;
+                locationItem.Longitude = geocoordinate.Longitude;
+                locationItem.Altitude = geocoordinate.Altitude;
+                locationItem.HorizontalAccuracy = geocoordinate.HorizontalAccuracy;
+                locationItem.VerticalAccuracy = geocoordinate.VerticalAccuracy;
+                locationItem.Speed = geocoordinate.Speed;
+                locationItem.Course = geocoordinate.Course;
+                locationItem.IsNewLocation = true;
+                locationItem.IsSelected = true;
+                locationItem.StoredTime = DateTime.Now;
             }
-
-            public static GeoCoordinate GetStoredGeoCoordinate()
+            else
             {
-                return new GeoCoordinate
-                    (
-                    StoredLocation.CurrentLatitude,
-                    StoredLocation.CurrentLongitude,
-                    StoredLocation.CurrentAltitude,
-                    StoredLocation.CurrentHorizontalAccuracy,
-                    StoredLocation.CurrentVerticalAccuracy,
-                    StoredLocation.CurrentSpeed,
-                    StoredLocation.CurrentCourse
-                    );
+                locationItem = new Location()
+                {
+                    Latitude = geocoordinate.Latitude,
+                    Longitude = geocoordinate.Longitude,
+                    Altitude = geocoordinate.Altitude,
+                    HorizontalAccuracy = geocoordinate.HorizontalAccuracy,
+                    VerticalAccuracy = geocoordinate.VerticalAccuracy,
+                    Speed = geocoordinate.Speed,
+                    Course = geocoordinate.Course,
+                    IsNewLocation = true,
+                    IsSelected = true,
+                    StoredTime = DateTime.Now
+                };
+
+                // Add a location item to the local database.
+                _locationDB.Locations.InsertOnSubmit(locationItem);
             }
         }
 
+        private GeoCoordinate ConvertLocation(Location locationItem)
+        {
+            return new GeoCoordinate
+                (
+                locationItem.Latitude,
+                locationItem.Longitude,
+                locationItem.Altitude,
+                locationItem.HorizontalAccuracy,
+                locationItem.VerticalAccuracy,
+                locationItem.Speed,
+                locationItem.Course
+                );
+        }
+
         private void mapWeatherInformation_Tap(object sender, System.Windows.Input.GestureEventArgs e)
         {
             var point = e.GetPosition(this.mapWeatherInformation);
             GeoCoordinate geocoordinate = this.mapWeatherInformation.ConvertViewportPointToGeoCoordinate(point);
             ReverseGeocodeAndUpdateMap(geocoordinate);
         }
-      
+
+        private async void GetCurrentLocationButton_Click(object sender, RoutedEventArgs e)
+        {
+            try
+            {
+                await this.GetCurrentLocationAndUpdateMap();
+            }
+            catch (Exception ex)
+            {
+                // TODO: make sure when exception in GetCurrentLocationAndUpdateMap we catch it here.
+                MessageBox.Show(
+                    AppResources.NoticeErrorLocationAutodetection,
+                    AppResources.UnavailableAutomaticCurrentLocationMessageBox,
+                    MessageBoxButton.OK);
+            }
+        }
+
         private void SaveLocationButton_Click(object sender, RoutedEventArgs e)
         {
             // TODO: Could there some problem if user clicks button and thread is in this very moment updating map?
@@ -240,7 +248,17 @@ namespace WeatherInformation
             // TODO: What if there is no city or country. Is there null value or empty string?
             //StoredLocation.City = address.City;
             //StoredLocation.Country = address.Country;
-            CoordinateHelper.StoreGeoCoordinate(geoCoordinate);
+            StoreLocation(geoCoordinate);
+        }
+
+        private void ZoomOutButton_Click(object sender, RoutedEventArgs e)
+        {
+            this.mapWeatherInformation.ZoomLevel = this.mapWeatherInformation.ZoomLevel - 1;
+        }
+
+        private void ZoomInButton_Click(object sender, RoutedEventArgs e)
+        {
+            this.mapWeatherInformation.ZoomLevel = this.mapWeatherInformation.ZoomLevel + 1;
         }
     }
 }
\ No newline at end of file
diff --git a/WindowsPhone/WeatherInformation/WeatherInformation/Model/Location.cs b/WindowsPhone/WeatherInformation/WeatherInformation/Model/Location.cs
new file mode 100644 (file)
index 0000000..1167e66
--- /dev/null
@@ -0,0 +1,296 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data.Linq;
+using System.Data.Linq.Mapping;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WeatherInformation.Model
+{
+    [Table]
+    public class Location : INotifyPropertyChanged, INotifyPropertyChanging
+    {
+        // Version column aids update performance.
+        [Column(IsVersion = true)]
+        private Binary _version;
+
+        private int _itemId;
+        [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
+        public int ItemId
+        {
+            get
+            {
+                return _itemId;
+            }
+            set
+            {
+                if (_itemId != value)
+                {
+                    NotifyPropertyChanging("ItemId");
+                    _itemId = value;
+                    NotifyPropertyChanged("ItemId");
+                }
+            }
+        }
+
+        private bool _isSelected;
+        [Column(CanBeNull = false)]
+        public bool IsSelected
+        {
+            get
+            {
+                return _isSelected;
+            }
+            set
+            {
+                if (_isSelected != value)
+                {
+                    NotifyPropertyChanging("IsSelected");
+                    _isSelected = value;
+                    NotifyPropertyChanged("IsSelected");
+                }
+            }
+        }
+
+        private double _latitude;
+        [Column(CanBeNull = false)]
+        public double Latitude
+        {
+            get
+            {
+                return _latitude;
+            }
+            set
+            {
+                if (_latitude != value)
+                {
+                    NotifyPropertyChanging("Latitude");
+                    _latitude = value;
+                    NotifyPropertyChanged("Latitude");
+                }
+            }
+        }
+
+        private double _longitude;
+        [Column(CanBeNull = false)]
+        public double Longitude
+        {
+            get
+            {
+                return _longitude;
+            }
+            set
+            {
+                if (_longitude != value)
+                {
+                    NotifyPropertyChanging("Longitude");
+                    _longitude = value;
+                    NotifyPropertyChanged("Longitude");
+                }
+            }
+        }
+
+        private double _altitude;
+        [Column(CanBeNull = false)]
+        public double Altitude
+        {
+            get
+            {
+                return _altitude;
+            }
+            set
+            {
+                if (_altitude != value)
+                {
+                    NotifyPropertyChanging("Altitude");
+                    _altitude = value;
+                    NotifyPropertyChanged("Altitude");
+                }
+            }
+        }
+
+        private double _horizontalAccuracy;
+        [Column(CanBeNull = false)]
+        public double HorizontalAccuracy
+        {
+            get
+            {
+                return _horizontalAccuracy;
+            }
+            set
+            {
+                if (_horizontalAccuracy != value)
+                {
+                    NotifyPropertyChanging("HorizontalAccuracy");
+                    _horizontalAccuracy = value;
+                    NotifyPropertyChanged("HorizontalAccuracy");
+                }
+            }
+        }
+
+        private double _verticalAccuracy;
+        [Column(CanBeNull = false)]
+        public double VerticalAccuracy
+        {
+            get
+            {
+                return _verticalAccuracy;
+            }
+            set
+            {
+                if (_verticalAccuracy != value)
+                {
+                    NotifyPropertyChanging("VerticalAccuracy");
+                    _verticalAccuracy = value;
+                    NotifyPropertyChanged("VerticalAccuracy");
+                }
+            }
+        }
+
+        private double _speed;
+        [Column(CanBeNull = false)]
+        public double Speed
+        {
+            get
+            {
+                return _speed;
+            }
+            set
+            {
+                if (_speed != value)
+                {
+                    NotifyPropertyChanging("Speed");
+                    _speed = value;
+                    NotifyPropertyChanged("Speed");
+                }
+            }
+        }
+
+        private double _course;
+        [Column(CanBeNull = false)]
+        public double Course
+        {
+            get
+            {
+                return _course;
+            }
+            set
+            {
+                if (_course != value)
+                {
+                    NotifyPropertyChanging("Course");
+                    _course = value;
+                    NotifyPropertyChanged("Course");
+                }
+            }
+        }
+
+        private string _city;
+        [Column(CanBeNull = false)]
+        public string City
+        {
+            get
+            {
+                return _city;
+            }
+            set
+            {
+                if (_city != value)
+                {
+                    NotifyPropertyChanging("City");
+                    _city = value;
+                    NotifyPropertyChanged("City");
+                }
+            }
+        }
+
+        private string _country;
+        [Column(CanBeNull = false)]
+        public string Country
+        {
+            get
+            {
+                return _country;
+            }
+            set
+            {
+                if (_country != value)
+                {
+                    NotifyPropertyChanging("Country");
+                    _country = value;
+                    NotifyPropertyChanged("Country");
+                }
+            }
+        }
+
+        private bool _isNewLocation;
+        [Column(CanBeNull = false)]
+        public bool IsNewLocation
+        {
+            get
+            {
+                return _isNewLocation;
+            }
+            set
+            {
+                if (_isNewLocation != value)
+                {
+                    NotifyPropertyChanging("IsNewLocation");
+                    _isNewLocation = value;
+                    NotifyPropertyChanged("IsNewLocation");
+                }
+            }
+        }
+
+        private DateTime _storedTime;
+        [Column(CanBeNull = false)]
+        public DateTime StoredTime
+        {
+            get
+            {
+                return _storedTime;
+            }
+            set
+            {
+                if (_storedTime != value)
+                {
+                    NotifyPropertyChanging("StoredTime");
+                    _storedTime = value;
+                    NotifyPropertyChanged("StoredTime");
+                }
+            }
+        }
+
+        #region INotifyPropertyChanged Members
+
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        // Used to notify the page that a data context property changed
+        private void NotifyPropertyChanged(string propertyName)
+        {
+            if (PropertyChanged != null)
+            {
+                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+            }
+        }
+
+        #endregion
+
+        #region INotifyPropertyChanging Members
+
+        public event PropertyChangingEventHandler PropertyChanging;
+
+        // Used to notify the data context that a data context property is about to change
+        private void NotifyPropertyChanging(string propertyName)
+        {
+            if (PropertyChanging != null)
+            {
+                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
+            }
+        }
+
+        #endregion
+    }
+}
diff --git a/WindowsPhone/WeatherInformation/WeatherInformation/Model/LocationDataContext.cs b/WindowsPhone/WeatherInformation/WeatherInformation/Model/LocationDataContext.cs
new file mode 100644 (file)
index 0000000..2e23844
--- /dev/null
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Data.Linq;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WeatherInformation.Model
+{
+    public class LocationDataContext : DataContext
+    {
+        // Specify the connection string as a static, used in main page and app.xaml.
+        public static string DBConnectionString = "Data Source=isostore:/Locations.sdf";
+
+        // Pass the connection string to the base class.
+        public LocationDataContext(string connectionString)
+            : base(connectionString)
+        { }
+
+        // Specify a single table for the location items.
+        public Table<Location> Locations;
+    }
+}
diff --git a/WindowsPhone/WeatherInformation/WeatherInformation/Model/Services/StoredLocation.cs b/WindowsPhone/WeatherInformation/WeatherInformation/Model/Services/StoredLocation.cs
deleted file mode 100644 (file)
index f563909..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO.IsolatedStorage;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace WeatherInformation.Model.Services
-{
-    // TODO: If I want to store more than one place I should use a database :(
-    // TODO: What if Double.NAN or null... Am I going to have some problem storing data in IsolatedStorageSettings?
-    class StoredLocation
-    {
-        public static double CurrentLatitude
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentLatitude"))
-                {
-                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentLatitude"];
-                }
-                // TODO: what if settings does not contain this value? :/
-                return 0;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["CurrentLatitude"] = value;
-            }
-        }
-
-        public static double CurrentLongitude
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentLongitude"))
-                {
-                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentLongitude"];
-                }
-                // TODO: what if settings does not contain this value? :/
-                return 0;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["CurrentLongitude"] = value;
-            }
-        }
-
-        public static double CurrentAltitude
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentAltitude"))
-                {
-                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentAltitude"];
-                }
-                // TODO: what if settings does not contain this value? :/
-                return 0;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["CurrentAltitude"] = value;
-            }
-        }
-
-        public static double CurrentHorizontalAccuracy
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentHorizontalAccuracy"))
-                {
-                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentHorizontalAccuracy"];
-                }
-                // TODO: what if settings does not contain this value? :/
-                return 0;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["CurrentHorizontalAccuracy"] = value;
-            }
-        }
-
-        public static double CurrentVerticalAccuracy
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentVerticalAccuracy"))
-                {
-                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentVerticalAccuracy"];
-                }
-                // TODO: what if settings does not contain this value? :/
-                return 0;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["CurrentVerticalAccuracy"] = value;
-            }
-        }
-
-        public static double CurrentSpeed
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentSpeed"))
-                {
-                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentSpeed"];
-                }
-                // TODO: what if settings does not contain this value? :/
-                return 0;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["CurrentSpeed"] = value;
-            }
-        }
-
-        public static double CurrentCourse
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentCourse"))
-                {
-                    return (double)IsolatedStorageSettings.ApplicationSettings["CurrentCourse"];
-                }
-                // TODO: what if settings does not contain this value? :/
-                return 0;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["CurrentCourse"] = value;
-            }
-        }
-
-        public static string City
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("City"))
-                {
-                    return (string)IsolatedStorageSettings.ApplicationSettings["City"];
-                }
-                return null;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["City"] = value;
-            }
-        }
-
-        public static string Country
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("Country"))
-                {
-                    return (string)IsolatedStorageSettings.ApplicationSettings["Country"];
-                }
-                return null;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["Country"] = value;
-            }
-        }
-
-        public static bool IsNewLocation
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("IsNewLocation"))
-                {
-                    return (bool)IsolatedStorageSettings.ApplicationSettings["IsNewLocation"];
-                }
-                return false;
-            }
-            set
-            {
-                IsolatedStorageSettings.ApplicationSettings["IsNewLocation"] = value;
-            }
-        }
-
-        public static bool IsThereCurrentLocation
-        {
-            get
-            {
-                if (IsolatedStorageSettings.ApplicationSettings.Contains("CurrentLatitude") &&
-                IsolatedStorageSettings.ApplicationSettings.Contains("CurrentLongitude"))
-                {
-                    return true;
-                }
-
-                return false;
-            }
-        }
-    }
-}
index 183482d..78a3a91 100644 (file)
@@ -38,5 +38,9 @@ namespace WeatherInformation.Model
             get;
             set;
         }
+
+        public string City { get; set;}
+
+        public string Country { get; set; }
     }
 }
index ac8fb74..94aff21 100644 (file)
@@ -106,24 +106,6 @@ namespace WeatherInformation.Resources {
         }
         
         /// <summary>
-        ///   Busca una cadena traducida similar a This app accesses your phone&apos;s location. Is that ok?.
-        /// </summary>
-        public static string AskForLocationConsentMessageBox {
-            get {
-                return ResourceManager.GetString("AskForLocationConsentMessageBox", resourceCulture);
-            }
-        }
-        
-        /// <summary>
-        ///   Busca una cadena traducida similar a Location.
-        /// </summary>
-        public static string AskForLocationConsentMessageBoxCaption {
-            get {
-                return ResourceManager.GetString("AskForLocationConsentMessageBoxCaption", resourceCulture);
-            }
-        }
-        
-        /// <summary>
         ///   Busca una cadena traducida similar a City, country.
         /// </summary>
         public static string LocationPageSubTitle {
@@ -304,6 +286,15 @@ namespace WeatherInformation.Resources {
         }
         
         /// <summary>
+        ///   Busca una cadena traducida similar a Current Location.
+        /// </summary>
+        public static string MapPageGetCurrentLocationButton {
+            get {
+                return ResourceManager.GetString("MapPageGetCurrentLocationButton", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Busca una cadena traducida similar a Save Location.
         /// </summary>
         public static string MapPageSaveLocationButton {
@@ -502,6 +493,15 @@ namespace WeatherInformation.Resources {
         }
         
         /// <summary>
+        ///   Busca una cadena traducida similar a The location master switch might be off or location service is unavailable..
+        /// </summary>
+        public static string UnavailableAutomaticCurrentLocationMessageBox {
+            get {
+                return ResourceManager.GetString("UnavailableAutomaticCurrentLocationMessageBox", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Busca una cadena traducida similar a http://api.openweathermap.org/data/{0}/weather?lat={1}&amp;lon={2}&amp;cnt=1.
         /// </summary>
         public static string URIAPIOpenWeatherMapCurrent {
index 1211412..fdb107b 100644 (file)
     <value>fahrenheit</value>
     <comment>Settings page, select temperature units fahrenheit</comment>
   </data>
-  <data name="AskForLocationConsentMessageBoxCaption" xml:space="preserve">
-    <value>Localización</value>
-    <comment>Ask for location consent in map window</comment>
-  </data>
   <data name="NoticeThereIsNotCurrentLocation" xml:space="preserve">
     <value>No hay localizaciones almacenadas.</value>
     <comment>Main window, notice message, no available locations</comment>
     <value>actual</value>
     <comment>Current header in main page</comment>
   </data>
-  <data name="AskForLocationConsentMessageBox" xml:space="preserve">
-    <value>Esta aplicación accede a los datos de tu localización. ¿Estás de acuerdo?</value>
-    <comment>Ask for location consent in map window</comment>
-  </data>
   <data name="MainPageTitle" xml:space="preserve">
     <value>Ciudad, país</value>
     <comment>Title in main page</comment>
     <value>Guardar posición</value>
     <comment>Map page, button saves the user's chosen location</comment>
   </data>
+  <data name="MapPageGetCurrentLocationButton" xml:space="preserve">
+    <value>Posición actual</value>
+    <comment>Map page, button get the user's current location</comment>
+  </data>
+  <data name="UnavailableAutomaticCurrentLocationMessageBox" xml:space="preserve">
+    <value>Detección automática de la ubicación parece estar desactivada en el teléfono o el servicio no está disponible.</value>
+    <comment>Message box error: while trying to get automatic current location</comment>
+  </data>
 </root>
\ No newline at end of file
index e2ef983..d281cf9 100644 (file)
           <target state="translated">fahrenheit</target>
           <note from="MultilingualBuild" annotates="source" priority="2">Settings page, select temperature units fahrenheit</note>
           </trans-unit>
-        <trans-unit id="Resx/AskForLocationConsentMessageBoxCaption" translate="yes" xml:space="preserve">
-          <source>Location</source>
-          <target state="translated">Localización</target>
-          <note from="MultilingualBuild" annotates="source" priority="2">Ask for location consent in map window</note>
-          </trans-unit>
         <trans-unit id="Resx/NoticeThereIsNotCurrentLocation" translate="yes" xml:space="preserve">
           <source>There is not stored locations.</source>
           <target state="translated">No hay localizaciones almacenadas.</target>
           <target state="translated">Guardar posición</target>
           <note from="MultilingualBuild" annotates="source" priority="2">Map page, button saves the user's chosen location</note>
           </trans-unit>
+        <trans-unit id="Resx/MapPageGetCurrentLocationButton" translate="yes" xml:space="preserve">
+          <source>Current Location</source>
+          <target state="translated">Posición actual</target>
+          <note from="MultilingualBuild" annotates="source" priority="2">Map page, button get the user's current location</note>
+          </trans-unit>
         <trans-unit id="Resx/SelectedDatePageMorning" translate="yes" xml:space="preserve">
           <source>MORNING</source>
           <target state="translated">MAÑANA</target>
           <source>ºC</source>
           <target state="needs-review-translation" state-qualifier="mt-suggestion">º C</target>
         </trans-unit>
-        <trans-unit id="Resx/AskForLocationConsentMessageBox" translate="yes" xml:space="preserve">
-          <source>This app accesses your phone's location. Is that ok?</source>
-          <target state="translated">Esta aplicación accede a los datos de tu localización. ¿Estás de acuerdo?</target>
-          <note from="MultilingualBuild" annotates="source" priority="2">Ask for location consent in map window</note>
-          </trans-unit>
         <trans-unit id="Resx/APIVersionOpenWeatherMap" translate="no" xml:space="preserve">
           <source>2.5</source>
           <target state="needs-review-translation" state-qualifier="mt-suggestion">2.5</target>
           <note from="MultilingualBuild" annotates="source" priority="2">Not to be translated.</note>
           </trans-unit>
+        <trans-unit id="Resx/UnavailableAutomaticCurrentLocationMessageBox" translate="yes" xml:space="preserve">
+          <source>The location master switch might be off or location service is unavailable.</source>
+          <target state="translated">Detección automática de la ubicación parece estar desactivada en el teléfono o el servicio no está disponible.</target>
+          <note from="MultilingualBuild" annotates="source" priority="2">Message box error: while trying to get automatic current location</note>
+          </trans-unit>
         <trans-unit id="Resx/URIAPIOpenWeatherMapForecast" translate="no" xml:space="preserve">
           <source>http://api.openweathermap.org/data/{0}/forecast/daily?lat={1}%%amp;lon={2}%%amp;cnt={3}%%amp;mode=json</source>
           <target state="needs-review-translation" state-qualifier="mt-suggestion">http://API.openweathermap.org/Data/ {0} / previsión/diario? lat = {1}%%amp;lon = {2}%%amp;cnt = {3}%%amp;mode = json</target>
index 3890ef8..d601dde 100644 (file)
           <target state="needs-review-translation" state-qualifier="mt-suggestion">[9AF14][!!_ƒáĥřêηĥęîţ_!!]</target>
           <note from="MultilingualBuild" annotates="source" priority="2">Settings page, select temperature units fahrenheit</note>
           </trans-unit>
-        <trans-unit id="Resx/AskForLocationConsentMessageBoxCaption" translate="yes" xml:space="preserve">
-          <source>Location</source>
-          <target state="new">Location</target>
-          <note from="MultilingualBuild" annotates="source" priority="2">Ask for location consent in map window</note>
-        </trans-unit>
         <trans-unit id="Resx/NoticeThereIsNotCurrentLocation" translate="yes" xml:space="preserve">
           <source>There is not stored locations.</source>
           <target state="new">There is not stored locations.</target>
           <target state="new">Save Location</target>
           <note from="MultilingualBuild" annotates="source" priority="2">Map page, button saves the user's chosen location</note>
         </trans-unit>
+        <trans-unit id="Resx/MapPageGetCurrentLocationButton" translate="yes" xml:space="preserve">
+          <source>Current Location</source>
+          <target state="new">Current Location</target>
+          <note from="MultilingualBuild" annotates="source" priority="2">Map page, button get the user's current location</note>
+        </trans-unit>
         <trans-unit id="Resx/SelectedDatePageMorning" translate="yes" xml:space="preserve">
           <source>MORNING</source>
           <target state="new">MORNING</target>
           <source>ºC</source>
           <target state="new">ºC</target>
         </trans-unit>
-        <trans-unit id="Resx/AskForLocationConsentMessageBox" translate="yes" xml:space="preserve">
-          <source>This app accesses your phone's location. Is that ok?</source>
-          <target state="new">This app accesses your phone's location. Is that ok?</target>
-          <note from="MultilingualBuild" annotates="source" priority="2">Ask for location consent in map window</note>
-        </trans-unit>
         <trans-unit id="Resx/APIVersionOpenWeatherMap" translate="yes" xml:space="preserve">
           <source>2.5</source>
           <target state="new">2.5</target>
           <note from="MultilingualBuild" annotates="source" priority="2">Not to be translated.</note>
         </trans-unit>
+        <trans-unit id="Resx/UnavailableAutomaticCurrentLocationMessageBox" translate="yes" xml:space="preserve">
+          <source>The location master switch might be off or location service is unavailable.</source>
+          <target state="new">The location master switch might be off or location service is unavailable.</target>
+          <note from="MultilingualBuild" annotates="source" priority="2">Message box error: while trying to get automatic current location</note>
+        </trans-unit>
         <trans-unit id="Resx/URIAPIOpenWeatherMapForecast" translate="yes" xml:space="preserve">
           <source>http://api.openweathermap.org/data/{0}/forecast/daily?lat={1}%%amp;lon={2}%%amp;cnt={3}%%amp;mode=json</source>
           <target state="new">http://api.openweathermap.org/data/{0}/forecast/daily?lat={1}%%amp;lon={2}%%amp;cnt={3}%%amp;mode=json</target>
index 5ad149f..fb63164 100644 (file)
     <value>2.5</value>
     <comment>Not to be translated.</comment>
   </data>
-  <data name="AskForLocationConsentMessageBox" xml:space="preserve">
-    <value>This app accesses your phone's location. Is that ok?</value>
-    <comment>Ask for location consent in map window</comment>
-  </data>
-  <data name="AskForLocationConsentMessageBoxCaption" xml:space="preserve">
-    <value>Location</value>
-    <comment>Ask for location consent in map window</comment>
+  <data name="UnavailableAutomaticCurrentLocationMessageBox" xml:space="preserve">
+    <value>The location master switch might be off or location service is unavailable.</value>
+    <comment>Message box error: while trying to get automatic current location</comment>
   </data>
   <data name="NoticeThereIsNotCurrentLocation" xml:space="preserve">
     <value>There is not stored locations.</value>
     <value>Save Location</value>
     <comment>Map page, button saves the user's chosen location</comment>
   </data>
+  <data name="MapPageGetCurrentLocationButton" xml:space="preserve">
+    <value>Current Location</value>
+    <comment>Map page, button get the user's current location</comment>
+  </data>
 </root>
\ No newline at end of file
index fc2cfca..6ab9fbb 100644 (file)
@@ -56,7 +56,7 @@ namespace WeatherInformation
                 {
                     MessageBox.Show(
                          AppResources.NoticeThereIsNotCurrentLocation,
-                         AppResources.AskForLocationConsentMessageBoxCaption,
+                         AppResources.UnavailableAutomaticCurrentLocationMessageBox,
                          MessageBoxButton.OK);
                     return;
                 }
index 6393509..a9e6aa1 100644 (file)
@@ -287,8 +287,8 @@ namespace WeatherInformation.ViewModels
                 NotifyPropertyChanged("CurrentSunSetText");
 
                 // TODO: What if address is not available? I should show something like "Address not found" by default...
-                string country = StoredLocation.Country;
-                string city = StoredLocation.City;
+                string country = weatherData.Country;
+                string city = weatherData.City;
                 string cityCountry = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", city, country);
                 this.TitleTextCityCountry = cityCountry;
                 NotifyPropertyChanged("TitleTextCityCountry");
index 93a4bc9..2cddabb 100644 (file)
@@ -207,8 +207,8 @@ namespace WeatherInformation.ViewModels
             NotifyPropertyChanged("SelectedDateNightTempUnits");
 
             // TODO: What if address is not available? I should show something like "Address not found" by default...
-            string country = StoredLocation.Country;
-            string city = StoredLocation.City;
+            string country = weatherData.Country;
+            string city = weatherData.City;
             string cityCountry = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", city, country);
             this.TitleTextCityCountry = cityCountry;
             NotifyPropertyChanged("TitleTextCityCountry");
index c5993ed..529e604 100644 (file)
     <Compile Include="Model\ForecastWeatherParser\Temp.cs" />
     <Compile Include="Model\ForecastWeatherParser\Weather.cs" />
     <Compile Include="Model\JsonDataParser\JsonParser.cs" />
-    <Compile Include="Model\Services\StoredLocation.cs" />
+    <Compile Include="Model\Location.cs" />
+    <Compile Include="Model\LocationDataContext.cs" />
     <Compile Include="Model\WeatherData.cs" />
     <Compile Include="Model\Services\CustomHTTPClient.cs" />
     <Compile Include="Model\Services\ServiceParser.cs" />