This is the continuation of “Simple Weather App in Xamarin Forms with MVVM using Weather API Part 1”

This part is where we will going to start coding and building our application.

Development Phase

5.0 Implementing WeatherAPI

5.1 Right click the folder “WeatherRestClient” and add new class file (Add -> Class…) and name it as “OpenWeatherMap” since we’re going to use their api service.

5.2 Inside the file, add these following codes including your api link and key.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
using Newtonsoft.Json;
using System.Net.Http;

namespace SimpleCrossWeatherApp.WeatherRestClient
{
    public class OpenWeatherMap<T>
    {
        private const string OpenWeatherApi = "http://api.openweathermap.org/data/2.5/weather?q=";
        private const string Key = "653b1f0bf8a08686ac505ef6f05b94c2";
        HttpClient _httpClient = new HttpClient();

        public async Task<T> GetAllWeathers(string city)
        {
            var json = await _httpClient.GetStringAsync(OpenWeatherApi + city + "&APPID=" + Key);
            var getWeatherModels = JsonConvert.DeserializeObject<T>(json);
            return getWeatherModels;
        }
    }
}

6.0 Creating Model Classes Based on Weather API

In OpenWeatherMapAPI, you can see the Json format for the possible model names using Advanced REST Client (or other tools)

Using this kind of tool, we are able to have the good visualization of “GET” result of our weather api.

For this demo, we’re going to use this single (class file) representing our main model:

  • WeatherMainModel.cs

6.1 Create this class file inside our “Models” folder by right clicking the folder -> Add -> Class… and name it as “WeatherMainModel.cs”

By looking at the “Get” response result from our web api, it returns different json properties. So, we need to add them inside our model in order to use them inside our project.

6.2 Add these following code snippets inside your WeatherMainModel class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
...
using Newtonsoft.Json;

namespace SimpleCrossWeatherApp.Models
{
    // serves as our main model in centralizing different classes
    public class WeatherMainModel
    {
        [JsonProperty("name")]
        public string name { get; set; }
        public WeatherTempDetails main { get; set; }
        public List<WeatherSubDetails> weather { get; set; }
        public WeatherWindDetails wind { get; set; }
        public WeatherSysDetails sys { get; set; }
    }
    
    public class WeatherSubDetails
    {        
        [JsonProperty("main")]
        public string main { get; set; }
        [JsonProperty("description")]
        public string description { get; set; }
        [JsonProperty("icon")]
        public string icon { get; set; }
    }

    public class WeatherSysDetails
    {
        [JsonProperty("country")]
        public string country { get; set; }
    }

    public class WeatherTempDetails
    {
        [JsonProperty("temp")]
        public string temp { get; set; }
        [JsonProperty("humidity")]
        public string humidity { get; set; }
    }

    public class WeatherWindDetails
    {
        [JsonProperty("speed")]
        public string speed { get; set; }
    }
}

We use different classes in order to match them to our web api request.

7.0 Creating Service Handler File between WeatherMainModel, OpenWeatherMap RestClient and ViewModels.

7.1 Go to “ServicesHandler” folder and add new class file by right clicking the folder -> Add -> Class… and name it as “WeatherServices.cs”

7.2 Add this code snippets for WeatherServices.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
using SimpleCrossWeatherApp.Models;
using SimpleCrossWeatherApp.WeatherRestClient;

namespace SimpleCrossWeatherApp.ServicesHandler
{
    public class WeatherServices
    {
        OpenWeatherMap<WeatherMainModel> _openWeatherRest = new OpenWeatherMap<WeatherMainModel>();
        public async Task<WeatherMainModel> GetWeatherDetails(string city)
        {
            var getWeatherDetails = await _openWeatherRest.GetAllWeathers(city);
            return getWeatherDetails;
        }
    }
}

8.0 Implementing INotifyPropertyChanged

8.1 Go to “ViewModels” folder and add new class file by right clicking the folder -> Add -> Class… and name it as “WeatherViewModel.cs”

8.2 Add NotifyProperty interface in your class in order to notify the binding client that the property has changed value.

1
2
3
4
5
6
7
8
9
10
...
using System.ComponentModel;

namespace SimpleCrossWeatherApp.ViewModels
{
    public class WeatherViewModel : INotifyPropertyChanged
    {
        ...
    }
}

8.3 Inside the WeatherViewModel class, add this code snippet in order to use the method OnPropertyChanged()

1
2
3
4
5
6
7
8
9
10
// import this for CallerMemberName
...
using System.Runtime.CompilerServices;

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

9.0 Creating Properties for Model and for the String Property of the “city” (string parameter)

9.1 Inside the WeatherViewModel, add this following code snippets.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// import these following references
...
using SimpleCrossWeatherApp.Models;
using SimpleCrossWeatherApp.ServicesHandler;

WeatherServices _weatherServices = new WeatherServices();

private WeatherMainModel _weatherMainModel;  // for xaml binding
public WeatherMainModel WeatherMainModel
{
    get { return _weatherMainModel; }
    set
    {
        _weatherMainModel = value;
        IconImageString = "http://openweathermap.org/img/w/" + _weatherMainModel.weather[0].icon + ".png"; // fetch weather icon image
        OnPropertyChanged();
    }
}

private string _city;   // for entry binding and for method parameter value
public string City
{
    get { return _city; }
    set
    {
        _city = value;
        Task.Run(async()=>{
            await InitializeGetWeatherAsync();
        });
        OnPropertyChanged();
    }
}

private string _iconImageString; // for weather icon image string binding
public string IconImageString
{
    get { return _iconImageString; }
    set 
    { 
        _iconImageString = value;
        OnPropertyChanged();
        }
    }
}

private bool _isBusy;   // for showing loader when the task is initializing
public bool IsBusy
{
    get { return _isBusy; }
    set
    {
        _isBusy = value;
        OnPropertyChanged();
    }
}

10.0 Adding Method to get the Returning Weather Details from WeatherServices

10.1 Add this following code snippets inside the WeatherViewModel

1
2
3
4
5
6
7
8
9
10
11
12
private async Task InitializeGetWeatherAsync()
{
    try
    {
        IsBusy = true; // set the ui property "IsRunning" to true(loading) in Xaml ActivityIndicator Control
        WeatherMainModel = await _weatherServices.GetWeatherDetails(_city);
    }
    finally
    {
        IsBusy = false;
    }
}

On the last page, we’ll going to create our UI Page for our simple weather app

Simple Weather App in Xamarin Forms with MVVM using Weather API Part 3

If you have some questions or comments regarding the Part 2 page, please drop it below. :)