So, you have heard the buzz about the brave new world of Windows 8 from MSFT’s BUILD Conference! May be you even attended the wonderful SilverlightShow webinar about “Getting Started with XAML Development in Windows 8” by Gill Cleeren.
Ready to get your hands muddy? In this short 2-part article series, we talk about how to get started towards writing data-driven (specifically OData) Windows 8 Metro apps with XAML & C#. Here’s what we’ll cover:
As always, the demo solution, along with all code samples is available for download through the link below:
Download Source Code
Introduction
At the BUILD Conference in August 2011, Microsoft launched Windows 8 .. the next iteration of Windows. It isn’t a forked world between desktop & mobile/tablet Operating Systems; rather “One OS to rule them all..” which runs on variety of form factors with touch-based interaction being a first-class citizen.
We could obviously talk a lot about Windows 8; but for the sake of the length of this blog post, let me refer you to 2 valuable resources:
- BUILD Website @ http://www.buildwindows.com/. Great place to start would be the 5 Keynotes, followed by tons of recorded Session content.
- Windows 8 Developer Home @ http://msdn.microsoft.com/en-us/windows/home. On this site is a link to download the Windows 8 Developer Preview – the latest Windows 8 bits along with Development tools. Also, as you get into serious Windows 8 Metro development, the samples from Microsoft & contributions from our fabulous community should be very valuable.
Also, check out the overall technology stack in Windows 8 below: [Source: Doug Seven’s Post]
A lot has been written in the past few months about Win RT & the development stack in Windows 8 .. simple web searches should get us lots of resources. For this article & the demo app, we will stick to the managed world of XAML UI & C# code running on .NET 4.5 on top of Win RT. There might be some rough edges .. but we are all trying to learn, right?
Prerequisites
To follow along or to try the Demo or build something similar yourself, you need the following:
- Windows 8 Developer Preview running “on the metal” on some laptop/tablet.
- Alternatively, you could also run Windows 8 in a VM (VirtualBox being the best fit at this time) or off a VHD.
- Visual Studio 11 included as a part of Windows 8 Developer Preview. At this point, the templates to build Metro Apps aren’t available outside the Windows 8 bits.
- Curiosity
The Data
Let’s try building a data-driven Metro App, shall we? For Demo purposes, I’m going to use a simple relational DB called “Demo” hosted in SQL Azure with just one table called “Team”, as shown below with schema/data:
So essentially, we want to keep track of Team Members with Names & TwitterHandles. How can we get this data easily into a Windows 8 Metro App? Why off course, OData !!
You may learn more about OData from http://www.odata.org/. I already have an OData Service built on top of our DB to expose the Team table data as an OData feed for consumption. Need to expose your data as OData? – Check out Michael Crump’s great series on Producing & Consuming OData in Silverlight & Windows Phone Applications.
Also, remember my article on Connecting Azure & Windows Phone through OData ? In that article, we talked about consuming OData from the same SQL Azure DB Table & also easily performing CRUD operations against data source through OData from a Windows Phone application. So essentially, we want to take the Windows Phone Demo application handling OData & port it over to being a Windows 8 Metro App in XAML & C#. You’ll soon realize that while we have to accommodate the UI having a lot more real estate in Windows 8, a lot of the coding artifacts are very similar or can be reused in the Windows 8 world with minor changes. If you have done Windows Phone Development, you should feel right at home in doing XAML Metro Apps!
So, here’s the OData service endpoint which provides access to our Table data in AtomPub (default) or JSon format:
The Metro App
So, now that we have a data source & an OData service on top of it exposing the data, let’s see how we may consume it in a Windows 8 Metro App. Let’s fire up Visual Studio 11 & make our appropriate selections as below:
The above selection gets us into a mode for building Metro Apps with XAML UI & C# code in a managed runtime. Just like in Windows Phone, the templates provided are your friends, as they get us a long way towards achieving Metro UI look & feel in our applications. For our demo, we shall choose to start with an empty application canvas & focus on fetching data into our app.
Now, since we have an OData service, it’ll be nice to Add a Service Reference to the service in our project so that we know the backend entities & can refer to them in code. Ouch – too soon The automatic proxy building against an OData service by adding a Service Reference isn’t quite ready in the Windows 8 tooling yet! So, we revert to the old-school way of adding our service reference into the project:
DataSvcUtil.exe /uri:Your_OData_Endpoint/out:TeamModel.cs /Version:2.0 /DataServiceCollection
As you could see, we used the DataSvcUtil tool (tucked away in your .NET Framework folder) to generate a proxy class which has all the entity bindings .. now we could simply drop the generated file into our project. Our project structure looks something like this .. the “Package.appxmanifest” file quite simply houses all your App configuration:
The UI
Don’t you wish you were working with a Team where every member is a Ninja? Well, let’s say that’s the case & we shall shoot for our Metro App UI to be something simple, like this:
The above screenshot is our Demo app running in the normal full-screen immersive UI mode. Notice how it is completely Chrome-free & puts content first. Just because we can clutter the UI with all kinds of controls, doesn’t mean that we should, right?
So, in our app, there is one & only XAML page that does the above rendering, that being MainPage.xaml. Here’s the XAML that drives the UI:
1: <UserControl x:Class="TeamMetro.MainPage"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6: mc:Ignorable="d"
7: d:DesignHeight="768" d:DesignWidth="1366">
8:
9: <!--Content-->
10: <Grid x:Name="LayoutRoot" Background="Chocolate">
11:
12: <StackPanel Background="Transparent" VerticalAlignment="Center" x:Name="fullMode">
13: <ListBox Name="fullTeamList" Margin="40" ItemsSource="{Binding WCFTeam}" Foreground="Blue" Background="Transparent">
14: <ListBox.ItemTemplate>
15: <DataTemplate>
16: <StackPanel Margin="400,0,0,40" VerticalAlignment="Center" Orientation="Horizontal">
17: <Image Source="ninja.png" Height="75" Width="75"/>
18: <TextBlock Text="{Binding Name}" Margin="10,0,0,0" FontSize="26" VerticalAlignment="Center"/>
19: <TextBlock Text=" -- aka " FontSize="22" VerticalAlignment="Center"/>
20: <TextBlock Text="{Binding TwitterHandle}" Margin="10,0,0,0" FontSize="22" VerticalAlignment="Center"/>
21: </StackPanel>
22: </DataTemplate>
23: </ListBox.ItemTemplate>
24: </ListBox>
25: </StackPanel>
26:
27: </Grid>
28:
29: </UserControl>
So, we essentially defined a ListBox & we are expecting it to be bound to some collection of Team members with appropriate property values. Did you notice that except for a few namespaces, the XAML markup is very similar to what we are used to seeing in Windows Phone & Silverlight applications? This is what should make you feel right at home .. there are off course, some Windows 8 specific UI controls, which can cover in a subsequent blog post.
Another point to note is that the XAML markup for Windows 8 Metro apps can be borrowed to a large extent if you have existing Windows Phone or Silverlight applications. In fact, if you have a a Windows Phone app in the Marketplace and simply want to port to over to the Windows 8 App Store, there are a fixed set of guidelines to do so, as explained here. However, we might need to be wary of a plain port-over & the UX of our Metro apps, since the Windows 8 tablet form factor will have substantially more real estate, which should absolutely be utilized. In our demo app, you see a simple list of data items consuming OData; while ok for a demo (see I excuse myself ), you ideally want to provide your users with a richer experience.
Fetching the Data
Now, this will be very interesting. One of the buzz terms with Windows Phone/Silverlight and now heavily so with Windows 8 is “fast & fluid” – which essentially means that your App may be doing some expensive operation; but to the end user interacting through Touch, it should always seem responsive. Asynchronous Programming is certainly not new & Windows Phone development very much enforces that; however, it may be a little painful at times, specially if you are marshaling data between threads or writing callback after callback.
Win RT enforces that any operation that might take more than 50 ms be done asynchronously, and this off course, extends to every web request our app might make. So, we are looking to fetch the OData feed asynchronously without blocking the UI thread.
Now, C# 5.0 running on .NET 4.5 framework tries to make it easy for us developers to do asynchronous programming through Async-Await patterns, so that we can get around not writing callback after callback or have to deal with thread marshaling. This however is a wider topic than this post – so please allow me to point you to some resources that should help understand this better:
- http://msdn.microsoft.com/en-us/library/hh191443(v=VS.110).aspx
- http://msdn.microsoft.com/en-us/vstudio/async.aspx
- http://msdn.microsoft.com/en-us/magazine/hh456402.aspx
I was intrigued about Asynchrony and wrote a lengthy post; if interested, you’ll find it HERE. So, let’s look at a few ways we can fetch data:
The Pure HTTP Way
In this approach, we make a basic HTTP Get call to our OData service endpoint & fetch data as Atom. This is simple, but we would have to manually parse the response to pluck out the data contents for binding to UI. Here’s some sample code .. watch the use of async-await to achieve asynchrony:
1: private async void LoadTeamThruXML()
2: {
3: // Get Atom over HTTP.
4: var client = new HttpClient();
5: Uri teamDataURI = new Uri("Your_OData_Endpoint");
6:
7: try
8: {
9: HttpResponseMessage response = await client.GetAsync(teamDataURI);
10:
11: string xmlResponse = response.Content.ReadAsString();
12: XDocument xDoc = XDocument.Parse(xmlResponse);
13:
14: // Do appropriate parsing.
15: // LINQ to XML.
16: IEnumerable<Team> teamCollection = from teamMember in xDoc.Descendants("Entry")
17: select new Team
18: {
19: Name = teamMember.Element("Name").ToString(),
20: TwitterHandle = teamMember.Element("TwitterHandle").ToString()
21: };
22:
23: // Bind to UI.
24: }
25: catch (Exception ex)
26: {
27: // Oopsie
28: }
29: }
The Threaded Way
One important aspect about Asynchrony is that it does not always mean multi-threading, as in parallelism. All the goodness of the Task Parallel Library is now built in and as we await on a Task, the underlying implementation may or may not spin up a new thread based on computing cycles needed. The point is, you should not have to care as a developer. However, if using Task.Factory, you are essentially carrying out synchronous operations on a worker thread without blocking the UI. So, here’s another way to fetch data .. notice how we can return a strongly-typed collection of Team members:
1: private async void LoadTeamThruOData()
2: {
3: var client = new Demo(new Uri("Your_OData_Endpoint"));
4:
5: var results = await Task<IEnumerable<Team>>.Factory.StartNew(() => FetchOData());
6:
7: // This fires only after we have a response back.
8: this.ParseAndBindData(results);
9: }
10:
11: private IEnumerable<Team> FetchOData()
12: {
13: Demo client = new Demo(new Uri("Your_OData_Endpoint"));
14: return client.Teams.Execute();
15: }
Wrapped APM Way
Asynchronous Programming Model (APM) is the traditional way of doing asynchrony through BeginXX/EndXX patterns; but this lead us to write a lot of callbacks. In the new world, APM calls can be wrapped inside an Async-Await pattern to make asynchronous requests. Let’s look at some code:
1: private async void LoadTeamThruOData()
2: {
3: var client = new Demo(new Uri("Your_OData_Endpoint"));
4:
5: var results = await Task<IEnumerable<Team>>.Factory.FromAsync(client.Teams.BeginExecute(AnotherEndContinuation, client), ContinuationDelegate);
6:
7: // This fires only after we have a response back.
8: this.ParseAndBindData(results);
9: }
10:
11: Func<IAsyncResult, IEnumerable<Team>> ContinuationDelegate = EndContinuation;
12: private static IEnumerable<Team> EndContinuation(IAsyncResult result)
13: {
14: Demo client = (Demo)result.AsyncState;
15: return client.Teams.EndExecute(result);
16: }
17:
18: private static void AnotherEndContinuation(IAsyncResult result)
19: {
20: // Do nothing here.
21: }
Now, the above code might look a little clunky, but the wrapping of the APM methods can be done through an Extension method to make reuse easier. Eventually with future updates, if we have a method Foo in our custom WCF Service, proxy integration should generate three method endpoints – BeginFoo, EndFoo & FooAsync. It is the last that we shall use comfortably with Async-Await patterns.
Data Updates?
So, by now we know how to fetch OData into a Windows 8 Metro app using XAML/C# and bind the results to a simple list. But what if we wanted to perform updates against the data source? That is absolutely possible since we are dealing with an OData service here. Unless blocked at the service side, OData will support full CRUD operations through the DataServiceContext & DataServiceCollection classes.
Now, let’s think about the UI for second. Just because we can put buttons & controls for data updates all over, doesn’t mean that we should. Common tasks should be presented in a minimalist fashion & accessible when needed. Accordingly, we revert to using the Windows 8 Metro Application Bar to add some metro buttons for allowing data manipulation. Let’s shoot for a UI like below .. we shall talk more about the Application Bar in the next article:
So, what happens when the user hits the Application Bar buttons? Simple – just like in Windows Phone, you can have event handlers assigned to each. Let’s see how we may delete a record & have it reflected in the OData data source, that is our Table data in SQL Azure. Here’s some code:
1: private void DeleteButton_Click(object sender, RoutedEventArgs e)
2: {
3: if (this.fullTeamList.SelectedItem != null)
4: {
5: Team selectedTeamMember = (Team)this.fullTeamList.SelectedItem;
6:
7: // LINQ to Context.
8: var client = new Demo(new Uri("Your_OData_Endpoint"));
9: var teamMemberToDelete = (from TeamMember in client.Teams
10: where TeamMember.Name == selectedTeamMember.Name
11: select TeamMember).First();
12:
13: // Delete backend entity.
14: client.DeleteObject(teamMemberToDelete);
15: client.BeginSaveChanges(new AsyncCallback(SaveDoneCB), client);
16: }
17: }
18:
19: private void SaveDoneCB(IAsyncResult asyncResult)
20: {
21: // Any error handling.
22: }
What about adding/editing records? Exactly the same way. Off of our “client” object above (which is in essence the DataServiceContext), you’ll see methods like AddObject & UpdateObject to insert/manipulate table records and then you simply need to call SaveChanges asynchronously to update the backend DB. You’ll see some sample code in the downloadable solution; but why not give it a shot yourself? You can get a lot of hints about how to perform CRUD operations against OData from a Windows Phone application from mine & Michael Crump’s articles HERE & HERE. So, go ahead & throw in a fresh XAML page to capture inserts/edits & fire away .
Summary
In this article, we talked about how to get started with Windows 8 Metro Apps with XAML/C# and we went on to consumption/updates of OData from a Windows 8 Metro application. We looked at a few techniques on how to do asynchronous programming in Windows 8 using the new C# 5.0 constructs of Async-Await. In the next part of article, we shall talk about taking the first steps towards making your Metro Apps feel at home in the Windows 8 Operating System.
I would appreciate any comments or concerns or how things could be done better. Thanks for reading & happy coding.
Cheers SilverlightShow!
About the Author
Samidip Basu (@samidip) is a technologist & gadget-lover working as a Manager & Solutions Lead for Sogeti out of the Columbus Unit. Having worked on WP7 since CTP days, he now spends much of his time in spreading the word to discover the full potential of the Windows Phone platform & cloud-based mobile solutions in general. He passionately runs the Central Ohio Windows Phone User Group (http://cowpug.org/), labors in M3 Conf (http://m3conf.com//) organization and can be found with at-least a couple of hobbyist projects at any time. His spare times call for travel and culinary adventures with the wife. Find out more at http://samidipbasu.com/.