Freigeben über


Data Binding Part 5- Dynamic Data from Rotten Tomatoes

In Part 1 of this series I covered the basic theoretical idea behind data binding, and in Part 2, we got a little more concrete with a hands on example in code.  We created a Movie class, then bound the three properties of that object (title, rating, year), to our UI in both Windows and Windows Phone projects using a Universal Windows App.  Then, in Part 3, we took a look at implementing the INotifyPropertyChanged interface and the difference in OneWay and TwoWay binding.  In Part 4, we took it one step further.  Instead of just displaying one movie to our UI, we bound a list of static movies using ListView and ObservableCollection.  Now, we are going to display a list of dynamics movie data powered by the Rotten Tomatoes API.

If you are not familiar with Rotten Tomatoes you can check out the site, Rotten Tomatoes.  In general, Rotten Tomatoes is a go to source for movies; what’s in theaters, what’s new on dvd, what’s new on TV, etc..  With their API, you can make a call to RT and they will send you back a list of movies with numerous properties (ratings, synopsis, urls to posters, etc.).  Is it starting to click how this information might fit what we are working on here?  You know, binding a list of movies to our UI and what not.  It’s a perfect fit!

To work with the RT API, you will need to sign up and get an API key from their developers website.  After you do that, you can also check out the documentation for the API itself.  I won’t cover it in depth here -you can read into it yourself- but the concept is simple.  Make a call with a url, and RT sends you back a list of movies.  For starters, the base URI is https://api.rottentomatoes.com/api/public/v1.0. From there you can tack on your specific search and your API key.  A great way to get started with this is use the IO-Docs page, which allows you “try” different requests and see what is returned.  I highly recommend trying a few of these before moving on.

Capture8

Just as a reference, in this example, I will be using the following request Uri, that will ask for a list of 16 movies in the box office in the United States. Obviously, you will need to replace [your-api-key] with your actual API key.

https://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=16&country=us&apikey=[your-api-key]

Now that we know a little bit about the RT API.  Let’s think about how we are going to use the JSON response that it sends us back.  The general idea is to make an HTTP request to the above url and convert that JSON string into a usable object in c#.  Therefore, we need to define an object that matches the model provided in the JSON response.  This might sound tedious since there are nested objects returned in each given query, but there’s hope in the form of a website called json2csharp.  With this website, you can simply give it a url that will return a json response, and it will generate the appropriate C# classes for us!  Trust me, this is great news and saves us a ton of time!

Capture10

Input the url above with your app id, and you will see the classes generated as below.

Capture9

If you scroll all the way down you can see the class for the root object, which is where we find the list of Movie objects as well as some links.

Capture11

Let’s now create a new class in our Shared project called RottenTomatoes.cs. We will simply copy all of the classes we just generated into our new RottenTomatoes class while making a few small changes.  I am going to take the properties of the RootObject and make them properties of RottenTomatoes class, and get rid of the RootObject class completely.  Then, I am going to rename the Movie class within our RottenTomatoes class to RTMovie to differentiate itself from the Movie class that we have worked with in the previous posts.  After I do all of this, my new class looks like this.

class RottenTomatoes
    {
         public List<RTMovie> movies { get; set; }
        public Links2 links { get; set; }
        public string link_template { get; set; }

        public class ReleaseDates
        {
             public string theater { get; set; }
            public string dvd { get; set; }
        }

        public class Ratings
         {
            public string critics_rating { get; set; }
             public int critics_score { get; set; }
            public string audience_rating { get; set; }
            public int audience_score { get; set; }
        }

        public class Posters
        {
            public string thumbnail { get; set; }
             public string profile { get; set; }
            public string detailed { get; set; }
            public string original { get; set; }
        }

        public class AbridgedCast
         {
            public string name { get; set; }
            public string id { get; set; }
            public List<string> characters { get; set; }
        }

        public class AlternateIds
        {
            public string imdb { get; set; }
         }

        public class Links
        {
            public string self { get; set; }
            public string alternate { get; set; }
            public string cast { get; set; }
             public string clips { get; set; }
            public string reviews { get; set; }
            public string similar { get; set; }
        }

        public class RTMovie
        {
             public string id { get; set; }
            public string title { get; set; }
            public int year { get; set; }
             public string mpaa_rating { get; set; }
            public int runtime { get; set; }
            public string critics_consensus { get; set; }
            public ReleaseDates release_dates { get; set; }
            public Ratings ratings { get; set; }
            public string synopsis { get; set; }
            public Posters posters { get; set; }
            public List<AbridgedCast> abridged_cast { get; set; }
            public AlternateIds alternate_ids { get; set; }
            public Links links { get; set; }
        }

        public class Links2
        {
            public string self { get; set; }
            public string alternate { get; set; }
        }
     }

Whew.  Ok we have the model for our RottenTomatoes object created, now we need to go our and get the response.  We will do this in our MoviesDataSource.cs file that we created in the last post.  In the LoadData() method, we will replace the static data with dynamic data from RT.  First let’s go ahead and create a constant string in this class for our url and call it API_CALL;

private const string API_CALL = "https://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=16&country=us&apikey=[your-api-key]";

The next step is to make the http call to that url using an instance of HttpClient class.  Since we will be using the getStringAsync method of the HttpClient class, our loadData() method will now need to be marked as Async.  We will then “await” that response and assign it to a string variable.  So far out method looks like this.

async private void loadData()
{
            HttpClient wc = new HttpClient();
             string response = await wc.GetStringAsync(API_CALL);
}

**If you aren’t familiar with Asynchronous programming, you can read up Here.**

We have our JSON response stored in the string called response, so now we need to convert that string to an instance of our RottenTomatoes object.  To do this, we will use a NuGet package called json.net.  To add a reference to this package, in your Solution Explorer right click on your solution and then Manage NuGet Packages.  Search for Json.net and click install.  If done successful, you should see it show up in your Windows and Windows Phone projects under the References folder as “Newtonsoft.Json” like so.

Capture12

With the reference to json.net we can use to now convert our json string and cast it to an instance of our RottenTomateos class with one line.

RottenTomatoes rt = (RottenTomatoes)JsonConvert.DeserializeObject<RottenTomatoes>(response);

Great now we have a RottenTomatoes object with all sorts of data, but we are just binding to a collection of Movie objects.  So, the last step is to convert each of the movies in the RottenTomatoes object to a Movie object and add them to our ObservableCollection.  We can use a simple foreach to iterate over each RTMovie object from the list of movies in the RottenTomateos object.  As we iterate, we can create a temp Movie object and set its fields appropriately from the fields of the RTMovie.  Ok, I admit that sounds pretty tricky, but let me show you the code.

foreach (RottenTomatoes.RTMovie m in rt.movies)
           {
                Movie temp = new Movie();
               temp.Title = m.title;
               temp.Rating = m.mpaa_rating;
                temp.Year = m.year.ToString();
               this.Add(temp);
           }

Basically we are copying over all of the RTMovies as Movie objects since our UI was designed to bind to a Movie object.  We could have just easily changed the binding of our UI to bind to a list of RTMovie objects instead.  Either way works fine.  So, when I run my app one last time I see a dynamic list of movie data.

Screenshot (215)

Again, this may not look super fancy, but if you are looking for UI design, you’ll have to find someone much more creative and artistic than myself.  Anyways, I hope this makes sense and that this series has helped to give you a thorough understanding of data binding, when and how to use it, and how it benefits you as a developer.  Thanks for following along the way!

Feel free to follow me on twitter for upcoming posts! @jquickwit  As always comment with any questions, comments, or concerns below!

Comments

  • Anonymous
    June 16, 2014
    This is an interesting series. Please add more series like this. Thanks

  • Anonymous
    June 17, 2014
    Glad to hear that!  I will try to follow up with more :)

  • Anonymous
    June 19, 2014
    Are there any examples of setting DataContext in the XAML rather than in the code-behind?  I would like to be able to use the DataBinding Intellisense in XAML, but have not been able to figure out how using the same data used in this tutorial.  It's a great tutorial, by the way

  • Anonymous
    August 01, 2014
    Thanks. I love it. You are the only one that makes me understand something of DataBinding. I hope to read more series like this too. :D

  • Anonymous
    January 31, 2015
    would it be possible to write an article about binding data in datagrid using WPF , C# and observable Collection here is what i mean: table columns are Number 1, Number 3, Result if you change number 1 or number 2 then the results are displayed in column Result i have been searching solution but could not find it. when i use onPropertyChanged i have to click on the Result column before i see re-calculation and i would like to get it done automatically

  • Anonymous
    September 14, 2015
    Hello. I have an issue. I have a class ClocksItem which has the following properties, string location, DateTime and a list of People People happens to be a class itself with string Name and string number as properties, I have succeeded in binding to a listView a list of ClockItems in the Master side of a MasterDetail presenter. Now  I want to bind the list of people to a listview in the contentPresenter of the Details side of the MasterDetail presenter. I would also like to potentially add people to the people list of individual clocksitems.