-
Notifications
You must be signed in to change notification settings - Fork 2
Article
TL;DR
I've made an application that works on Windows Universal 10 devices. It gives the forecast for several cities in this world by an API (application programming interface) from Yahoo. It contains the MVVM (model view view-model) pattern (more specific MVVM light library) and IoC (inversion of control) architectures. I use also SQLite (structured query language lite) database for storing the search results. But what are there? Here comes some information:
MVVM is a software architectural pattern and it's build in tree parts like it said. In your project you have tree parts: models, views and view-models like show on image below.
The models go access the database, but for this project I use API's from Yahoo mapped into the folder Repositories.
View-models contains ICommands
and some binding properties. All view models inherit form ViewModelBaseClass
where the interface INotifyPropetyChanged
has been implemented.
The last part are the views. This contains the XAML pages and data templates. The last one is stored into the folder DataTemplates.
Each part is communicate witch each other:
- The views with the view models,
- The view models with the models (and repositories),
- The repositories access the API (or another data source).
In theories is this correct, but in practical situations communicate the view also with the models. This must be for the data bindings of the element properties to the model properties.
On the image there stand also a fourth part named unit tests. This are tests you can make for testing your code. This is not implement in the project and not explained in this article.
IoC containers are container with basic functionality needed to register and resolve instances. For the project we go use the SimpleIoc class from MVVM light. The methods we go use in these project are:
Name | Description |
---|---|
Register<TClass>(Boolean) |
Registers a given type with the possibility for immediate creation of the instance. |
GetInstance<TService>() |
Provides a way to get an instance of a given type. If no instance had been instantiated before, a new instance will be created. If an instance had already been created, that same instance will be returned. Remark: If the class is not registered, the method will return null. |
For more information and methodes you can read the documentation on mvvmlight.net.
There is also a default constructor without parameters that initializes a new instance of the SimpleIoc
class.
Dependency injection is a way of working that allow you to make code independent of the class where you are working on. For this you can use interfaces. Thy defined only the signature of the methods, properties and variables. An example you can use is to use a dummy class when developing or a web service when deploying. Here you've a code expample:
public interface IDataSource
{
IEnumarble<object> Get(); // used for get all the objects
}
public class DummySource : IDataSource
{
public IEnumarble<object> Get()
{
return new List<object> {
new { Letter = "A", Number = "1" },
new { Letter = "A", Number = "1" }
}
}
}
public class WebSource : IDataSource
{
public IEnumarble<object> Get()
{
//return all objects of a web service
}
}
On the place where you call the Get()
method, it doesn't matter what the class is. It could be the dummy class or the webservice.
Note: on the place where you call the method, don't use the classes but use the interface like code below:
IDataSource source = new DummySource();
IEnumarble<object> dummyData = source.Get();
source = new WebSource();
IEnumarble<object> webData = source.Get();
This code will work because the variable source, is independent from the class DummySource
and WebSource
because I've made a "wrapper" interface named IDataSource
that have a signature of the methodes.
In the solution I've made three projects named:
-
Data
contains repositories for access the API. Download the NuGetNewtonsoft.Json
package for this project. -
Models
contains the classes we needed -
UWP
what stands for universal Windows 10 project and has following folders:-
Assets
is default folder added in the project and contains images for the logo into the Windows store. -
DataTemplates
for store data templates -
Pages
contains the pages we go use -
Services
contains the IoC container -
ViewModels
contains the view models and one folder *core
for store the core data
-
We also need some NuGet packages you can download it from the NuGet manager. For the data project is this Newtonsoft.JSON
and for the UWP project we need MvvmLight
.
If the UWP project is made, you see next items into that project
- Properties contains the properties of that project.
- References contains the references needed for that project.
- The folders we've just created.
-
App.xaml
contains important recourses and information about your project. -
MainPage.xaml
is the first page that is show when the application run. Package.appxmanifest
project.json
Wheater.UWP_TemporaryKey.pfx
First we need MainPage.xaml
.
An API is a service for getting routines, protocols, tools or data powered by other instances (like Yahoo) that software programmers can access into there programs, applications and websites. But can find by robots, Dominica, drones and much more.
First of all we must access the API from Yahoo to get the data from. The URL (uniform recourse locator) that we go use is this:
https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places%20where%20text%3D%22@placemame%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys
I've found the URL on developer.yahoo.com/weather/. You see the parameter q what is a SQL statement:
SELECT *
FROM weather.forecast
WHERE woeid
IN (SELECT woeid
FROM geo.places
WHERE text = @placemame)
This go select all the fields of the table weather.forecast where woeid
(WOEID stands for where on earth identifier) is equal with the value of the select from the table geo.places
where the text field is equal to variable @placename
. This variable must have a value so that the URL is valid in this case is this a string or for say it into SQL language is this from the type nvarchar
or text
depended from the used SQL language by Yahoo.
On the URL above you can also see a second parameter called format. For this example we go use JSON (JavaScript object notation) as receiving value.
If you navigate to to the URL you see this JSON code. Here you've the forecast from March 1st 2016 from Meenen, Belgium:
{
"query":{
"count":1,
"created":"2016-03-01T17:31:15Z",
"lang":"en-US",
"results":{
"channel":{
"title":"Yahoo! Weather - Meenen, BE",
"link":"http://us.rd.yahoo.com/dailynews/rss/weather/Meenen__BE/*http://weather.yahoo.com/forecast/FRXX4403_f.html",
"description":"Yahoo! Weather for Meenen, BE",
"language":"en-us",
"lastBuildDate":"Tue, 01 Mar 2016 6:00 pm CET",
"ttl":"60",
"location":{
"city":"Meenen",
"country":"Belgium",
"region":""
},
"units":{
"distance":"mi",
"pressure":"in",
"speed":"mph",
"temperature":"F"
},
"wind":{
"chill":"37",
"direction":"200",
"speed":"20"
},
"atmosphere":{
"humidity":"93",
"pressure":"29.83",
"rising":"0",
"visibility":"3.73"
},
"astronomy":{
"sunrise":"7:28 am",
"sunset":"6:30 pm"
},
"image":{
"title":"Yahoo! Weather",
"width":"142",
"height":"18",
"link":"http://weather.yahoo.com",
"url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"
},
"item":{
"title":"Conditions for Meenen, BE at 6:00 pm CET",
"lat":"50.8",
"long":"3.12",
"link":"http://us.rd.yahoo.com/dailynews/rss/weather/Meenen__BE/*http://weather.yahoo.com/forecast/FRXX4403_f.html",
"pubDate":"Tue, 01 Mar 2016 6:00 pm CET",
"condition":{
"code":"26",
"date":"Tue, 01 Mar 2016 6:00 pm CET",
"temp":"45",
"text":"Cloudy"
},
"description":"\n<img src=\"http://l.yimg.com/a/i/us/we/52/26.gif\"/><br />\n<b>Current Conditions:</b><br />\nCloudy, 45 F<BR />\n<BR /><b>Forecast:</b><BR />\nTue - Showers Late. High: 48 Low: 42<br />\nWed - PM Rain/Wind. High: 48 Low: 36<br />\nThu - Showers/Wind. High: 44 Low: 34<br />\nFri - Showers. High: 45 Low: 31<br />\nSat - PM Showers. High: 46 Low: 33<br />\n<br />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Meenen__BE/*http://weather.yahoo.com/forecast/FRXX4403_f.html\">Full Forecast at Yahoo! Weather</a><BR/><BR/>\n(provided by <a href=\"http://www.weather.com\" >The Weather Channel</a>)<br/>\n",
"forecast":[
{
"code":"45",
"date":"1 Mar 2016",
"day":"Tue",
"high":"48",
"low":"42",
"text":"Showers Late"
},
{
"code":"12",
"date":"2 Mar 2016",
"day":"Wed",
"high":"48",
"low":"36",
"text":"PM Rain/Wind"
},
{
"code":"11",
"date":"3 Mar 2016",
"day":"Thu",
"high":"44",
"low":"34",
"text":"Showers/Wind"
},
{
"code":"11",
"date":"4 Mar 2016",
"day":"Fri",
"high":"45",
"low":"31",
"text":"Showers"
},
{
"code":"39",
"date":"5 Mar 2016",
"day":"Sat",
"high":"46",
"low":"33",
"text":"PM Showers"
}
],
"guid":{
"isPermaLink":"false",
"content":"FRXX4403_2016_03_05_7_00_CET"
}
}
}
}
}
}
Of course you could make the correct C# classes manually, but on the internet, you have some easy tools that do this for you. One of they is json2csharp.com (only to C#) or jsonutils.com (many other languages) that convert all the code for you. Import the classes to your project by copy past them and rename RootObject
to YahooWheater
.
Make a new class into the data project named WebRepo
and place this code for use the API.
public class WebRepo
{
public static async YahooWeather GetData(string placename)
{
try
{
using (HttpClient client = new HttpClient())
{
string url = $@"https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places%20where%20text%3D%22{placemame}%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
string yahooGeoJSON = await client.GetStringAsync(url);
return JsonConvert.DeserializeObject<YahooWeather>(yahooGeoJSON);
}
}
catch
{
return null;
}
}
}
Later we'll make dependency injection for this class.
Also posted on CodeProject