Advertisement
Windows Phone

Using Silverlight to Create a Digg Client for Windows Phone 7

by

Silverlight is the main application development platform for Windows Phone 7. In a previous tutorial we covered how to get your system set up for Windows Phone 7 development and then we developed a very simple Silverlight application that rotated a button around a grid. This article will introduce you to more advanced Silverlight features and will enable you to develop meaningful applications that display data in interesting and unique ways.

This article will introduce you to a number of intermediate-level Windows Phone 7 and Silverlight features including application resources, styles, data templates, and view navigation. You’ll take advantage of data binding and WP7 services that allow you to navigate between pages quickly and easily. You should have some familiarity of XAML and C# before beginning this tutorial.

Creating Your Project

In this tutorial, you’re going to create a simple Digg client that allows a user to browse stories by topic. You’ll take advantage of intermediate-level Silverlight and Windows Phone 7 features including application resources, styles, data templates, and navigation services. You’ll use data binding to display information from Digg and various WP7 services to allow users to get around your application.

To get started, make sure you have the latest Windows Phone 7 development tools installed on your computer. The tools were updated on July 12, 2010 so you may need to uninstall a previous CTP and install the tools Beta.

Open Visual Studio 2010 and click New Project in the left sidebar. In the dialog that pops up, select “Windows Phone Application” from the available templates and give your project a name like “SimpleDigg.” Make sure that the “Create directory for solution” toggle is checked and then click “OK.” Your setting should look like the following:

Silverlight Project Creation

After your project is created, Visual Studio opens MainPage.xaml for editing. Close this file for now.

Creating Digg Data Classes

To access Digg’s data, we’ll use their official API. In particular, we’ll be using the story.getAll and topic.getAll methods. Example responses for each call can be found at the following URLs:

As you can see, story.getAll returns story items. Stories have a lot of data associated with them, but we’re going to focus on 4 pieces of information:

  • Title
  • Description
  • Diggs
  • Link

Let’s create the class to hold this data. In Visual Studio’s Solution Explorer (which is open by default in the right sidebar), right-click on your Project and choose “Add > New Folder”. Name this new folder Digg. Right-click on your newly created folder and choose “Add > Class…”. Name your class Story and click the Add button.

Visual Studio will open your new class for editing. Inside the class definition add four public properties like the following:

public string Title { get; set; }
public string Description { get; set; }
public string Link { get; set; }
public int Diggs { get; set; }

Now, add the class that will hold Topic data. Right-click on your Digg folder again and choose “Add > Class…”. Name your class Topic and add the following properties when the file opens:

public string Name { get; set; }
public string ShortName { get; set; }

At this point, you’ve created all the data classes you’ll need for this tutorial and are ready to markup the views needed for the rest of the application.

Creating Views

The SimpleDigg client has three different views that need to be created. They are:

  • Topic List – Lists all topics on Digg
  • Story List – Lists stories retrieved from Digg based on a particular topic
  • Story Detail – Shows details about a selected story

Topics List

The Topic List will be the first screen that users see when they start your application. It comprises a list of topic names which, when one of the topic is clicked, leads to a list of stories in that topic. Since this will be the first screen that users see, we’ll go ahead and use the previously created MainPage.xaml file that already exists in the Project. Open MainPage.xaml and you should see a visual representation on the left and the markup for the view on the right.

Click on the text “My Application” in the visual representation and notice that a TextBlock element in the XAML representation is highlighted. That TextBlock has a Text attribute currently occupied by the value “MY APPLICATION.” Change that value to whatever you want. I recommend “Simple Digg.” You’ll see that the visual designer updates to match your changes.

Now, repeat the process with the “page name” string. Click on the text, find the appropriate TextBlock and modify the Text attribute. This time, I recommend changing it to “Topics”. If you’ve done everything correctly up to this point, you should have a StackPanel element that contains two @TextBlock@s, each with an appropriate value. The XAML looks like the following:

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="24,24,0,12">
    <TextBlock 
        x:Name="ApplicationTitle" 
        Text="Simple Digg" 
        Style="{StaticResource PhoneTextNormalStyle}"/>
    <TextBlock 
        x:Name="PageTitle" 
        Text="Topics" 
        Margin="-3,-8,0,0" 
        Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

Now, you need to add the list container to your page. Open up the Control Toolbox (located on the left of Visual Studio) and drag a ListBox item into the big blank area on your page. You need to modify it to stretch the width and height of it’s container, so put your cursor in the XAML editor and modify the ListBox element to read like the following:

<ListBox 
    Name="TopicsList" />

This markup removes all the styling that the visual designer introduced and renames the element so that you can access elements in it. At this point, you’ve completed the markup for the Topics List view and can now move onto the the other parts of the application

Story List

The story list view is very similar to the topic list. For organizational purposes, we’re going to put this view (and later, the Story Detail view) inside of a separate folder. Right-click on your project’s name in the Solution Explorer and choose “Add > New Folder.” Name the new folder Views. Then, right-click on the Views folder and choose “Add > New Item…” Select the Windows Phone Portrait Page template and name it Stories.xaml. Your dialog box should look like the following:

Creating a new Windows Phone Portrait Page

Now, as before, change the application title to “Simple Digg” and the page name to “Stories.” Next, drag a ListBox onto the blank space underneath your page title and modify it’s markup to look like the following:

<ListBox
    Name="StoriesList" />

At this point your story list view looks nearly identical to your topic list. The real differences will show up when you populate them with data items.

Story Details

The final view for your application is the Story Details view. The Story Details view will present the 4 pieces of data that we talked about earlier:

  • Title
  • Description
  • Diggs
  • Link

The number of Diggs and title will occupy the top of the view and the story description will follow underneath. After that, a link will will allow the user to navigate to the story in question if they wish.

As before, right-click on the Views folder in your project and choose Add > New Item. Select the Windows Phone Portrait Page template and name your new view Story.xaml. Click Add and Visual Studio will create Story.xaml and open it for editing.

Change the application title and page title textblocks to read “Simple Digg” and “Story” respectively. Now, drag a StackPanel into the blank space underneath your page title. Drag another StackPanel into the previous StackPanel. This StackPanel will contain the story title and Digg count. You want these items to align next to each other, so change the Orientation property to Horizontal.

Finally, drag a TextBlock and a Button into your first StackPanel. The TextBlock will contain the story description while the Button will allow the user to visit the story source. You’re going to need to do some extensive property modification to these elements and, rather than run through them one by one, just make sure your markup looks like the following:

<StackPanel Name="StoryDetails">
    <StackPanel 
        Orientation="Horizontal" Name="StoryDetailsHeader">
        <TextBlock 
            Name="NumberDiggs" 
            Text="10" />
        <TextBlock 
            Name="Title" 
            Text="Story Title Goes Here" />
    </StackPanel>
    <TextBlock 
        Name="Description" 
        Text="The story description will go here.  This text will wrap, as you can see right here." 
        TextWrapping="Wrap" />
    <Button 
        Content="Read Full Story" 
        Name="Link" 
        Width="200" />
</StackPanel>

You can see we’ve removed most explicit Height and Width properties and changed Text and Name properties to something a little bit more descriptive. It looks a bit ugly right now, but we’ll fix that up later. If you’ve got everything marked up corrrectly then your visual designer pane should look like the following:

The Story Details view before being styled.

At this point, the basics of all the necessary views are done. You can hit F5 to fire up the application to confirm that everything is working, but you’ll just get a blank screen with “Topics” at the top.

Customizing the Navigation Mapper

The next thing you need to do is make sure that you can direct users around your application. To do so, you’ll use Silverlight’s navigation mapping with a few simple rules. Open your project’s App.xaml file and place your cursor inside of the opening Application element and add a new namespace as follows:

xmlns:nav="clr-namespace:System.Windows.Navigation;assembly=Microsoft.Phone"

This references the Windows System Navigation namespace (a Silverlight feature) and allows you to use the various library classes that exist within it. Now, find the Application.Resources element in App.xaml and add the following elements:

<nav:UriMapper x:Key="UriMapper">
    <nav:UriMapper.UriMappings>
        <nav:UriMapping Uri="/Topics" MappedUri="/MainPage.xaml" />
        <nav:UriMapping Uri="/Topics/{topic}" MappedUri="/Views/Stories.xaml?Topic={topic}" />
        <nav:UriMapping Uri="/Story" MappedUri="/Views/Story.xaml" />
    </nav:UriMapper.UriMappings>
</nav:UriMapper>

The code you just entered creates a variety of URI mappings for the views within your application. They correspond to the topics list, story list, and story detail views respectively. As you can see, Silverlight navigation mapping allows you to define query variables inside of your custom mappings. This will come in handy later when we go to actually populate data.

You’re not done with URI mapping, though. You need to tell your application to use this UriMapper, so open the App.xaml code behind by clicking the arrow next to App.xaml and opening App.xaml.cs. Inside of the App method after the call to InitializePhoneApplication() add the following statement:

RootFrame.UriMapper = Resources["UriMapper"] as UriMapper;

This statement tells your application to use the UriMapper you just defined in XAML for your phone app. Now, let’s start populating some data.

Populating the Topic List

The first thing we need to do is populate the Topic list. We’ll do this when the user first navigates to the MainPage.xaml page. To make sure this happens, you’ll override the OnNavigatedTo method for the MainPage class. Open MainPage.xaml.cs by clicking the arrow next to MainPage.xaml. Place your cursor after the constructor and add the following code:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    WebClient digg = new WebClient();
    digg.DownloadStringCompleted += new DownloadStringCompletedEventHandler(digg_DownloadStringCompleted);
    digg.DownloadStringAsync(new Uri("http://services.digg.com/1.0/endpoint?method=topic.getAll"));
}

void digg_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{

}

You can see that inside of the OnNavigatedTo method you create a WebClient object, assign it an event handler for when a string is downloaded, and then instruct it to download the string from the Digg topic.getAll method URL. We know that the string to be downloaded will be in XML format, so we need to make sure our event handler can parse the XML. For this purpose we’ll use the Linq libraries available in the .NET framework. Before we can utilize those library classes, though, we’ll have to add a reference to the library. Right-click on the “References” item in your Solution Explorer pane and choose “Add Reference…” From the list that pops up, select System.Xml.Linq and click “OK.”

Now, you just need to fill in the event handler that you created. Change digg_DownloadStringCompleted so it looks like the following:

void digg_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    if(e.Error != null) {
        return;
    }

    XElement topicXml = XElement.Parse(e.Result);

    var topics = from topic in topicXml.Descendants("topic")
                    select new Topic
                    {
                        Name = topic.Attribute("name").Value,
                        ShortName = topic.Attribute("short_name").Value
                    };
    TopicsList.ItemsSource = topics;
}

First, you check to see if the download was completed successfully. If it was, then you parse the resultant string and generate a collection of topics using Linq to XML. If you’re interested, you can read more about Linq to XML at the official MSDN site.

Finally, you assign the ItemsSource property of the TopicsList to the topics you parsed out. If you see a squiggly line under Topic, then place your cursor after it, click the down arrow that appears under the word, and select “using SimpleDigg.Digg”. At this point, you’ve got your topics populated so fire up your phone emulator by pressing F5 and you should see something like the following:

First try at populating the topics list.

As you can see, your list has been populated but the correct data is not being displayed. Let’s take care of that now.

Data Templates

Data template are one of the most powerful tools in your Silverlight toolkit. They allow you to define the markup that should be shown for arbitrary objects. At this point, we’ll define DataTemplates for Digg Topics and Stories. Open App.xaml and place your cursor inside of the Application.Resources element. Add the following element:

<DataTemplate x:Key="TopicTemplate">
    <TextBlock
        FontSize="48" 
        Text="{Binding Name}" />
</DataTemplate>

This DataTemplate provides contains a simple TextBlock element which is bound to the Name property of the object being displayed. If you remember, the Digg.Topic class contains a Name property which is set to the name attribute returned from the Digg topics API call. Return to your MainPage.xaml and find the ListBox element. Add a new property ItemTemplate to the ListBox as follows:

ItemTemplate="{StaticResource TopicTemplate}"

This line of code instructs the application to use your previously created DataTemplate resource to display the Topic objects that make up the ListBox’s collection. If you press F5 and run your application, you’ll see that Topic names are properly displayed now:

Topic names being displayed appropriately.

Fetching and Displaying Stories

At this point we’re ready to start fetching stories per topic and listing them. First, we need to tell the application that when a topic title is tapped the application should navigate to the stories list. Open MainPage.xaml and find your ListBox element. Add the SelectionChanged property and allow Visual Studio to create a new event handler. In MainPage.xaml.cs, change your event handler so it reads something like the following:

private void TopicsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Topic topic = TopicsList.SelectedItem as Topic;
    NavigationService.Navigate(new Uri("/Topics/"+topic.ShortName, UriKind.Relative));
}

If you run your application now (by pressing F5), you can see that you navigate to the Stories page whenever you select a topic. Now, we just need to actually populate the story list and make them display appropriately. As we did earlier, we’re going to override the OnNavigatedTo method to make that happen. Open Views/Stories.xaml.cs and add the following code:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    String name;
    NavigationContext.QueryString.TryGetValue("Topic", out name);

    WebClient client = new WebClient();
    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
    client.DownloadStringAsync(new Uri("http://services.digg.com/1.0/endpoint?method=story.getAll&topic=" + name));
}

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    if (e.Error != null)
    {
        return;
    }

    XElement storyXml = XElement.Parse(e.Result);

    var stories = from story in storyXml.Descendants("story")
                    select new Digg.Story
                    {
                        Title = story.Element("title").Value,
                        Description = story.Element("description").Value,
                        Diggs = Int32.Parse(story.Attribute("diggs").Value),
                        Link = story.Attribute("link").Value
                    };
    StoriesList.ItemsSource = stories;
}

A lot of this will look familiar. The only part that may look odd is retrieving the topic name. If you recall, you mapped /Topics/{topic} to /Views/Stories.xaml?Topic={topic}. That is, you allow the Topic query string variable to be passed in a friendly format. When we navigated from the topics list, we passed the topic shortname in the relative Uri. In the code above, when the stories list is being navigated to we retrieve this variable and use it to call the Digg API URL with a specific topic.

We know that if we fire up our application at this point we’re not going to get the kind of appearance we want for our story listing. Let’s define another DataTemplate to use in this view. Open up App.xaml and add the following code to your Application.Resources element.

<DataTemplate x:Key="StoryTemplate">
    <StackPanel Orientation="Horizontal" Margin="5">
        <Grid Background="Yellow">
            <TextBlock
                FontSize="48" 
                Foreground="DarkGray" 
                Height="60" 
                TextAlignment="Center" 
                Text="{Binding Diggs}" 
                VerticalAlignment="Center" 
                Width="60" />
        </Grid>
        <TextBlock
            FontSize="24" 
            Margin="10,0,0,0" 
            MaxWidth="400" 
            Padding="5" 
            Text="{Binding Title}" 
            TextWrapping="Wrap" />
    </StackPanel>
</DataTemplate>

Now, open up Views/Stories.xaml and modify your ListBox element so it reads as follows:

<ListBox 
    ItemTemplate="{StaticResource StoryTemplate}" 
    Name="StoriesList" 
    ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
    />

Run your application by pressing F5 and click on a topic name. Wait a moment, and you’ll see your stories appear. The next thing we have to do is display story details on the detail page.

Displaying Story Details

In order to display story details, we need to first allow navigation to the story detail page and then we’ll handle displaying data. In the story list, we have a number of story items. When one of them is selected we want to store that Story object somewhere and then use it on the story details page. To do so, we’ll add an event handler to the SelectionChanged event as follows:

private void StoriesList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    PhoneApplicationService.Current.State["Story"] = StoriesList.SelectedItem;
    NavigationService.Navigate(new Uri("/Story", UriKind.Relative));
}

Here, you’re storing the selected story in the PhoneApplicationService class’s State property as recommended by the execution model best practices. If you have a red squiggly line under PhoneApplicationService then place your cursor inside the word and then select the dropdown that appears and choose “using Microsoft.Phone.Shell”.

Now, we need to retrieve this on the other end. Open up your Views/Story.xaml.cs and add the following code that overrides OnNavigatedTo:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    Digg.Story story = PhoneApplicationService.Current.State["Story"] as Digg.Story;
    this.DataContext = story;
}

Here, you intercept the navigation to the story details view, retrieve the story stored in the PhoneApplicationService’s State property, and then remove the story from the PhoneApplicationService’s State collection. You then set the DataContext for the view to the story retrieved. This is key, as we’ll use this binding to make display the appropriate data.

Open your markup for the story details view in Views/Story.xaml. Modify it to use bindings as follows:

<StackPanel Name="StoryDetails">
    <StackPanel 
        Name="StoryDetailsHeader" 
        Orientation="Horizontal">
        <Grid Background="Yellow" Margin="5">
            <TextBlock 
                FontSize="48" 
                Foreground="DarkGray" 
                Height="60" 
                TextAlignment="Center" 
                Text="{Binding Diggs}" 
                VerticalAlignment="Center" 
                Width="60" />
        </Grid>
        <TextBlock 
            Margin="5" 
            Name="Title" 
            Text="{Binding Title}" 
            TextWrapping="Wrap" />
    </StackPanel>
    <TextBlock 
        Margin="10" 
        Name="Description" 
        Text="{Binding Description}" 
        TextWrapping="Wrap" />
    <Button 
        Content="Read Full Story" 
        Name="Link" 
        />
</StackPanel>

If you launch your application now (press F5) you will be able to drill down from the topic list, to the story list, to full story details. The story details view should look something like the following:

The story details view.

There’s only one last thing to do. Add a click event handler to the Link button in Views/Story.xaml as follows:

<Button 
    Content="Read Full Story" 
    Name="Link" 
    Click="Link_Click" 
    />

Change your event handler, Link_Click, to read like the following:

private void Link_Click(object sender, RoutedEventArgs e)
{
    WebBrowserTask task = new WebBrowserTask();
    task.URL = (this.DataContext as Digg.Story).Link;
    task.Show();
}

If you see a red squiggly line under WebBrowserTask, then place your cursor over the class and then select “using Microsoft.Phone.Tasks” from the dropdown that appears. This code launches the Windows Phone 7 web browser when clicking on the button and navigates it to the story’s URL.

Finishing Up

You have a fully functioning, albeit simple, Digg client at this point. You can browse stories by topics, view story details and visit the full story in the WP7 web browser. In this tutorial we’ve:

  • Created classes to store Digg data
  • Created and customized application views using the visual designer
  • Customized navigation URIs and used the Windows Phone 7 Navigation service
  • Implemented DataTemplates and Styles to display stories and topics
  • Overrode the OnNavigatedTo and OnNavigatedFrmo event handlers to provide appropriate functionality for each page
  • Used the Windows Phone 7 tasks to launch a web browser

Some of the topics we covered are far to in-depth to cover in a simple tutorial so you’ll probably want to find out more about them. The following resources should help you get started:

I hope you’ve enjoyed this tutorial. If you have any questions or want to see something different in a future Windows Phone 7 tutorial, let me know in the comments.

Related Posts
  • Code
    Android SDK
    Create a Music Player on Android: Project Setup0d63m preview image@2x
    The Android platform provides resources for handling media playback, which your apps can use to create an interface between the user and their music files. In this tutorial series, we will create a basic music player application for Android. The app will present a list of songs on the user device, so that the user can select songs to play. The app will also present controls for interacting with playback and will continue playing when the user moves away from the app, with a notification displayed while playback elapses.Read More…
  • Code
    Theme Development
    Custom Controls in the Theme CustomizerTheme customizer custom control 400
    In the last article, we explored the advanced controls available in the Theme Customizer, and how to implement them. We’re going to look at how to create our own custom control, allowing you to choose which Category of Posts are displayed on the home page. To get started, download version 0.6.0 of our Theme Customizer Example.Read More…
  • Web Design
    UX
    Walk Users Through Your Website With Bootstrap TourTour retina
    When you have a web application which requires some getting used to from your users, a walkthrough of the interface is in order. Creating a walkthrough directly on top of the interface makes things very clear, so that's what we're going to build, using Bootstrap Tour.Read More…
  • Computer Skills
    OS X
    50 Things You Probably Didn't Know About OS X MavericksMavericks400
    Mavericks, the latest major release of OS X (pronounced Oh-Es Ten), is version 10.9 of Apple’s desktop operating system. With, reportedly, over 200 new features Mavericks is no incremental update. Jonny Ive might suggest that “Apple has reimagined the operating system for the desktop”, but the truth is Apple has incorporated some of the best ideas from third-party developers and has sought to integrate some of the features of iOS (the operating system for the iPod Touch, iPhone and iPad) into it’s desktop big brother.Read More…
  • Code
    PHP
    How to Accept Payments With StripeCode
    Processing credit cards is unfortunately far more difficult than we might hope, as developers. Given that it’s such a common task, is it really necessary that we jump through countless hoops (surrounded by fire, of course) for the sole purpose of processing a payment? Merchants? Gateways? SSL? Security? Very quickly, a seemingly simple operation can become an overwhelmingly confusing and, more importantly, dangerous task. Any time that you find yourself handling a user’s sensitive data, you better be on your toes. Read More…
  • Computer Skills
    Terminal
    40 Terminal Tips and Tricks You Never Thought You NeededIcon terminal 2x
    The Terminal is an exceptionally powerful tool, providing a command line interface to the underpinnings of OS X. It’s a topic we’ve covered at length before with our popular series Taming the Terminal. There’s a great deal that Terminal can do, from moving large numbers of files to changing preferences that we didn’t even know exist. To demonstrate just how versatile the Terminal is, I’ve rounded up 40 truly excellent Terminal tips and tricks that can come in very handy. Read More…