Introduction
This demo has the main goal to show the steps that are needed to consume an OData service in Windows Store Apps, and use the MVVM Pattern and has Ioc container for managing the dependencies.
Building the Sample
You only need Visual Studio 2012 and Windows 8, both the RTM version.
Description
For concretizing this sample, I used the Netflix OData Catalog API (Preview), that can be found where:
For those who is starting with OData service in Windows Store Apps, I recommend to install the:
“The WCF Data Services Tools for Windows Store Apps installer extends the Add Service Reference experience with client-side OData support for Windows Store Apps in Visual Studio 2012.”
Here are the main points:
- Creating a blank project like you can see in the image below
- Add Service Reference
- Analizing the NetflixService
- The
IServiceManager
, FakeServiceManager
and ServiceManager
- The
LoadNewDVDMoviesAsync
method - The
LoadTopDVDMoviesAsync
method - The
DataServiceContextAsyncExtension
- The model
- The
TitlesViewModel
- The
LoadDataAsync
method - The
GroupView
and ItemView
- Binding the view model with the view
ViewModelLocator
- In App.xaml
- In the TitlesPage.xaml
- In the TitlesPage.xaml.cs
- Binding Data
- The output / running the demo
- Fiddler
Let’s Start
1. Create a Blank Project like you can see in the following image:

Note: I used te name Netflix.ClientApp
(Win8) for the project, but I will change the namespace
for Netflix.ClientApp
and in the future if I need to create the Netflix.ClientApp
(WP8, I can use the same namespace
and if I need to “linked as” some file, I will not have problems with namespace
s.
2. Add Service Reference


The service reference that I added is: http://odata.netflix.com/v2/Catalog/.
3. Analyzing the NetflixService
The result will be:

Note: This is not required, but you can create a class diagram that will show all classes and its properties, method and events. It helps to understand that was added when you added the service reference.

4. The IServiceManager, FakeServiceManager and the ServiceManager
Now the project has the service, and I decided to get the top of the DVD Movies and the new releases of the DVD Movies. With this, I will define an interface
for my service manager.
Here is the code:
public interface IServiceManager
{
Task<IEnumerable> LoadNewDVDMoviesAsync();
Task<IEnumerable> LoadTopDVDMoviesAsync();
}
The fake implementation will be:
FakeServiceManager
public class FakeServiceManager : IServiceManager
{
private readonly BitmapImage _bitmapSoure;
public FakeServiceManager()
{
_bitmapSoure = new BitmapImage(new Uri("ms-appx:///Images/FakeImage.png"));
}
public IEnumerable CreateItems(int number)
{
var myTitles = new List<MyTitle>();
for (var i = 0; i < number; i++)
{
myTitles.Add(new MyTitle
{
Name = string.Concat("Fake Name ", i),
AvailableFrom = DateTime.Now,
Rating = 0,
Image = _bitmapSoure
});
}
return myTitles;
}
public async Task<IEnumerable> LoadNewDVDMoviesAsync()
{
return await Task.Run(() => CreateItems(20));
}
public async Task<IEnumerable> LoadTopDVDMoviesAsync()
{
return await Task.Run(() => CreateItems(20));
}
}
The implementation for the real service will be:
ServiceManager
public class ServiceManager : IServiceManager
{
private readonly NetflixCatalog _netflixCatalog;
public ServiceManager()
{
_netflixCatalog = new NetflixCatalog(new Uri("http://odata.netflix.com/v2/Catalog/"),
UriKind.Absolute);
}
public async Task<IEnumerable> LoadNewDVDMoviesAsync()
{
var query = ((DataServiceQuery<Title>)_netflixCatalog.Titles.Where
(title => title.ReleaseYear >= 2012
&& title.Dvd.Available
&& title.Type == "Movie")
.OrderByDescending(item => item.Dvd.AvailableFrom)
.Take(30)).Expand(item => item.Genres).Expand
(item => item.Directors);
var result = await query.ExecuteAsync();
return ConvertToMyTitles(result);
}
public async Task<IEnumerable> LoadTopDVDMoviesAsync()
{
var query = ((DataServiceQuery<Title>)_netflixCatalog.Titles.Where
(title => title.ReleaseYear >= 2012
&& title.Dvd.Available
&& title.Type == "Movie")
.OrderByDescending(item => item.AverageRating)
.Take(20)).Expand(item => item.Genres).Expand
(item => item.Directors);
var result = await query.ExecuteAsync();
return ConvertToMyTitles(result);
}
private IEnumerable ConvertToMyTitles(IEnumerable<Title> titles)
{
return
titles.Select(
title =>
new MyTitle
{
Name = title.Name,
Image = new BitmapImage(new Uri(title.BoxArt.MediumUrl)),
AvailableFrom = title.Dvd.AvailableFrom,
Rating = title.AverageRating
}).ToList();
}
}
Here, there are two important methods:
LoadNewDVDMoviesAsync
LoadTopDVDMoviesAsync
4.1. The LoadNewDVDMoviesAsync Method
First, I will create the query that will be used for the service request:
var query = ((DataServiceQuery<Title>)_netflixCatalog.Titles.Where(
title => title.ReleaseYear >= 2012 &&
title.Dvd.Available &&
title.Type == MovieStringValue)
.OrderByDescending(item => item.Dvd.AvailableFrom)
.Take(30))
.Expand(item => item.Genres)
.Expand(item => item.Directors);
Here, I want all titles that release year is greater than 2012 and DVD
is available and type is Movie
and I want these title order by data from DVD is available. At the end, I only want the first 30 items and I want with Genres and Directors filled.
4.2. The LoadTopDVDMoviesAsync Method
In this method, the query will be:
var query = ((DataServiceQuery<Title>)_netflixCatalog.Titles.Where(
title => title.ReleaseYear >= 2012 &&
title.Dvd.Available &&
title.Type == MovieStringValue)
.OrderByDescending(item => item.AverageRating)
.Take(20))
.Expand(item => item.Genres)
.Expand(item => item.Directors);
Here, I want all titles for which release year is greater than 2012
and DVD
is available and type is Movie
and I want these titles
ordered by average rating. At the end, I only want the first 20 items and I want with Genres
and Directors
properties filled.
4.3. The DataServiceContextAsyncExtensions
Inside both methods, I will execute the query like this:
var result = await query.ExecuteAsync();
and it will make a call to the server and request the data.
For simplicity of the calls, I added DataServiceContextAsyncExtension
that allow to use the async
and await
keyworks.
public static class DataServiceContextAsyncExtensions
{
public static async Task<IEnumerable<TResult>> ExecuteAsync<TResult>
(this DataServiceQuery<TResult> query)
{
return await Task.Factory.FromAsync<IEnumerable<TResult>>
(query.BeginExecute(null, null), query.EndExecute);
}
}
4.4 The Model
Here is the class diagram:

GroupView
is used to group a list of itemview
that can have a MyTitle
or Title
object (depends if your view depends on the service data or not, if yes when there is an update, you may need to udpate the view and the viewmodel. If not, you only need to update the ConvertToMyTitles
method in ServiceManager
.
Note: This solution is good when you have for example:
Group 1 with a list of A data type elements and a Group 2 with a list of B data type elements.
You only need to create a similar class. I do so with MyTitleItemView
or TitleItemView
and the binding as easy and only need to define one ItemTemplateSelector
that will choose the correct DataTemplate
(normally by data type or group when both groups has the same data type).
5. The TilesViewModel
Because I am using the MVVM pattern, I will call these methods in my view model, I could implement it inside of the view model but I don't want to have dependencies in my view model.
In the view model, I will have:
public TitlesViewModel(IServiceManager serviceManager, INavigationService navigationService)
{
IsToShowProgress = true;
_serviceManager = serviceManager;
_navigationService = navigationService;
}
and inside the LoadDataAsync
, I will have:
public async Task LoadDataAsync()
{
IsToShowProgress = true;
try
{
var newDVDMovies = _serviceManager.LoadNewDVDMoviesAsync();
var topDVDMovies = _serviceManager.LoadTopDVDMoviesAsync();
await Task.WhenAll(new Task[] { newDVDMovies, topDVDMovies });
if (newDVDMovies.IsCompleted && topDVDMovies.IsCompleted)
{
Groups = new List<GroupView>
{
ViewModelHelper.GetGroupView(NameDefinitions.TopDVDMoviesId,
NameDefinitions.TopDVDMoviesLabel, topDVDMovies.Result),
ViewModelHelper.GetGroupView(NameDefinitions.NewDVDMoviesId,
NameDefinitions.NewDVDMoviesLabel, newDVDMovies.Result)
};
}
else
{
ErrorMessage = GetErrorMessage(newDVDMovies, topDVDMovies);
}
IsToShowProgress = false;
}
catch (Exception exception)
{
IsToShowProgress = false;
ErrorMessage = exception.Message;
}
}
Here, it is important to refer that I will do two service requests at the same time and wait until both are finished. This is great because I don´t need to request one by one and the time spent with the request is the maximum of both.
6. Binding the View Model with the View
6.1. ViewModelLocator
This class contains the SimpleIoc
for dependency injection and helps to binding the view model with the view.
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (!SimpleIoc.Default.IsRegistered<IServiceManager>())
{
SimpleIoc.Default.Register<IServiceManager, ServiceManager>();
}
SimpleIoc.Default.Register<TitlesViewModel>();
}
public TitlesViewModel TitlesViewModel
{
get
{
return ServiceLocator.Current.GetInstance<TitlesViewModel>();
}
}
}
6.2. In App.xaml
<viewModel:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
6.3. In the TitlesPage.xaml
DataContext="{Binding TitlesViewModel, Source={StaticResource Locator}}"
Here is defined the DataContext
and with this all the page can be binding to the view model.
6.4. In the TitlesPage.xaml.cs
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
if (_titlesViewModel != null)
{
await _titlesViewModel.LoadDataAsync();
}
}
Here is the moment the view model will load the data.
6.5 Binding Data
In TitlesPage.xaml, I have a CollectionViewSource
that allows to define what is the source and in grouped data, which are the path of the Items
.
<CollectionViewSource
x:Name="GroupedItemsViewSource"
Source="{Binding Groups}"
IsSourceGrouped="true"
ItemsPath="Items"
d:Source="{Binding Groups}"/>
This will help to group data in GridView
.
<GridView
x:Name="ItemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
Visibility="{Binding IsToShowProgress,
Converter={StaticResource NagationBooleanToVisibilityConverter}}"
Padding="116,0,40,46"
IsSwipeEnabled="True"
IsItemClickEnabled="True"
ItemClick="ItemGridViewOnItemClick"
ItemsSource="{Binding Source={StaticResource GroupedItemsViewSource}}"
ItemTemplateSelector="{StaticResource NetFlixItemTemplateSelector}"
SelectionMode="Single" ItemContainerStyle="{StaticResource GridViewItemStyle}">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal">
<VirtualizingStackPanel.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition />
<RepositionThemeTransition />
</TransitionCollection>
</VirtualizingStackPanel.ChildrenTransitions>
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Margin="1,0,0,6">
<Button
AutomationProperties.Name="Group Title"
Style="{StaticResource TextPrimaryButtonStyle}" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Label}"
Margin="3,-7,10,10"
Style="{StaticResource GroupHeaderTextStyle}" />
<TextBlock Text="{StaticResource ChevronGlyph}"
FontFamily="Segoe UI Symbol"
Margin="0,-7,0,10"
Style="{StaticResource GroupHeaderTextStyle}"/>
</StackPanel>
</Button>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Orientation="Vertical" Margin="0,0,80,0"/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
And the...
<templateSelector:NetFlixItemTemplateSelector x:Key="NetFlixItemTemplateSelector"/>
...will help to define the ItemTemplate
that will be applied in each group.
Each item data template is defined in Template.xaml:
<DataTemplate x:Key="TopDVDMoviesItemTemplate">
<Grid HorizontalAlignment="Left" Width="82"
Height="120" Background="#B9090B">
<Image Source="{Binding Item.BoxArt.MediumUrl}"
Width="82" Height="120"
CacheMode="BitmapCache" Stretch="Uniform" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="NewDVDMoviesItemTemplate">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left" Width="300" Height="120">
<Image CacheMode="BitmapCache" Source="{Binding Item.BoxArt.MediumUrl}"
Width="82" Stretch="Uniform" Margin="10,10,5,10"/>
<StackPanel Margin="10,10,5,10">
<TextBlock Text="{Binding Item.Name}"
TextWrapping="Wrap" Margin="0,0,5,0"/>
<StackPanel Orientation="Horizontal" Margin="0,10,10,0">
<TextBlock Margin="0,0,5,5" Text="Rating:" />
<TextBlock Margin="0,0,0,5" Text="{Binding Item.AverageRating}" />
</StackPanel>
<StackPanel Orientation="Vertical" Margin="0,0,10,0" >
<TextBlock Margin="0,0,0,5" Text="Available:" />
<TextBlock Text="{Binding Item.Dvd.AvailableFrom,
Converter={StaticResource StringFormatConverter},
ConverterParameter=\{0:d MMMM yyyy\}}"
TextWrapping="Wrap" />
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
7. The Output/Running the Demo
The result of the TitlesPage
is:

8. Fiddler
In fiddler, we can see the service requests:

GET
/v2/Catalog/Titles()?$filter=ReleaseYear%20ge%202012%20and%20Dvd/Available%20and%20Type%20eq%20′Movie’
&$orderby=Dvd/AvailableFrom%20desc&$top=30&$expand=Genres,Directors
HTTP/1.1
GET
/v2/Catalog/Titles()?$filter=ReleaseYear%20ge%202012%20and%20Dvd/Available%20and%20Type%20eq%20′Movie’
&$orderby=AverageRating%20desc&$top=20&$expand=Genres,Directors
HTTP/1.1
Notes
For using Fiddler with Windows 8 Store Apps, the Win8 config is required to be installed.
See the Fiddler Extensions.
Other Notes
- Because I am using MVVM Light, from this library I used:
(It is not the unique solution.)
- Because this is a demo, maybe there are some points related with UI that are not completed, I focused on the propose of the sample. In the future, I would like to work more in this sample and implement more sample using this sample.
Source Code Files
The solution has the following structure:

Details:
- IServiceManager.cs has the
IServiceManager interface
and define the interface
for the ServiceManager
. - ServiceManager.cs has the
ServiceManager
class and it encapsulate the NetFlixService
and exposes only the methods that are needed in ViewModel
. - FakeServiceManager.cs is the implementation of the
IServiceManager
, but is a fake data.
- TitlesViewModel.cs has
TitlesViewModel
class and it is used for binding with the DataContext
from TitlesPage
. - ViewModelLocator.cs has the
ViewModelLocator
class that helps to bind the view model with the view. - ViewModelHelper.cs has the
ViewModelHelper
class the helps to create grouped data.
- TitlesPage.xaml and TitlesPage.xaml.cs that is the main page.
- Templates.xaml is a resource dictionary that has the
DataTemplate
for the view. - NetFlixItemTemplateSelector.cs has the
NetFlixItemTemplateSelector
that is used for get the ItemTemplate
for each item in gridView
.
More Information
Run the sample
To debug the app and then run it, press F5 or use Debug > Start Debugging. To run the app without debugging, press Ctrl+F5 or use Debug > Start Without Debugging.
More Information
Ask me on twitter @saramgsilva
Official Source