Click here to Skip to main content
15,867,704 members
Articles / Programming Languages / C#

Introduction to Windows Phone 7 Silverlight Development: Making an Off Line RSS Reader

Rate me:
Please Sign up or sign in to vote.
4.78/5 (10 votes)
15 Jul 2010CPOL7 min read 77.2K   2K   34   18
Introduction to Windows Phone 7 Silverlight development: Making an Off Line RSS Reader

Introduction

In a few months, Microsoft will bring the new version of its mobile operating system, Windows Phone 7 with many new, controversial, supporters and retractors ...

But today, let's take a look from our point of view, the programmers. Microsoft has given a great advantage to those who use WPF / Silverlight. For now, we are also developers for Windows Phone 7, as all applications for this O.S. are developed in XNA or Silverlight.

This is a revolution compared to Windows Mobile 6.X or other competitors mobile platforms, because it will allow us to port applications that are already working on Silverlight in a fast and simple way, almost without rewriting code.

To get a bit to the development of an application made in Silverlight for Windows Phone 7 as an example, I bring you an RSS reader (very basic, no commercial aspirations or anything) in which we will use several interesting things about Silverlight and Windows Phone 7:

  • Application Bar
  • Access to local storage of our terminal
  • Object serialization and deserialization
  • Use of the WebClient class
  • Use of the webBrowser control to load dynamic generated content

The final result of our application:

Captura_2.PNG

Starting

In order to develop applications for Windows 7 Phone, you need to download the CTP of the tools of development here.

This pack includes Visual Studio 2010 Express for Windows Phone, so if you do not have Visual Studio 2010, you will not have problems in developing for Windows Phone 7.

Once the Developers tools have been installed, just open Visual Studio 2010 and choose a new Silverlight for Windows Phone project as shown in the image:

Captura3.PNG

The project is in Visual C#, do not look at Visual Basic, it is not found, yet. For now, there is only support for C#, but the Windows Phone has promised that the final version of the SDK will have support for Visual Basic. But in the end, really all of it is .NET and the two languages do not change so much.

ApplicationBar

The ApplicationBar is a wonderful idea of design from the Windows Phone 7 team to help us create the interface of our applications, you can see it in detail in this capture:

Captura4.PNG

The bottom bar violet with the 3 points is the application bar, clicking on the 3 points is displayed showing all available options:

Captura5.PNG

It is very useful because it allows us to create a menu that can be included on each page of the application you want to just add a reference, since the definition of the menu is in the file App.xaml and the code associated with each option in the file app.xaml.cs. Consider the code required to define the application XAML bar.

First, our project should include a reference to the assembly Microsoft.Phone.Shell.

Then, our App.xaml should include a reference to Microsoft.Phone.Shell:

XML
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;
             assembly=Microsoft.Phone.Shell"

Finally in the Tag <Application.Resources>, create our Application Bar:

XML
<shell:ApplicationBar x:Name="MenuAppBar" Opacity="0.7"
                       IsVisible="True" IsMenuEnabled="True"
                       BackgroundColor="Purple" >
    <shell:ApplicationBar.MenuItems>
        <shell:ApplicationBarMenuItem Text="Edit Rss Sources"
                                       x:Name="EditRss"
                                       Click="EditRss_Click"/>
        <shell:ApplicationBarMenuItem Text="Update Local Rss"
                                       x:Name="UpdateRss"
                                       Click="UpdateRss_Click"/>
        <shell:ApplicationBarMenuItem Text="View Local Rss"
                                       x:Name="ViewRss"
                                       Click="ViewRss_Click"/>
    </shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>

Now on each page where you want to display the ApplicationBar, you must indicate the attribute ApplicationBar of the object <navigation:PhoneApplicationPage>:

XML
<navigation:PhoneApplicationPage
     ...
     ...
    ApplicationBar="{StaticResource MenuAppBar}">

With this, if we run our application, we will see that our Application Bar appears and is displayed showing all options.

To add code to each option, we use the Click event in XAML we defined earlier, for example, the Edit RSS Sources option calls the event EditRss_Click, which is located in the file app.xaml.cs and has this signature:

C#
private void EditRss_Click(object sender, EventArgs e)
{
    //Do something awesome here!
} 

As you can see, the method EditRss_Click signature is the same as the Click event of any button.

Access to Local Storage, Serialize and Deserialize Objects

One of the major changes in development between Windows Mobile 6.X and Windows Phone 7 is that our applications do not have permission to access the general storage terminal on which are stored and cannot use databases in the terminal.

To meet this guideline for Microsoft is clear: move your data to the cloud and your application can access them through your Internet connection. Although this is totally true, we can find times when we want to store some information on the terminal as a data cache or store user preferences on the application and its status. This we do by going to IsolatedStorage assigned to our application. This storage space is isolated from the rest of the system and applications, and is exclusive to our application.

Let's say we want to save a file in this isolated storage that contains all the RSS feeds you have configured in our application. This is very simple using the XML serialization and deserialization and decorating our class with the necessary XML attribute.

For this, we need first to add to our project a reference to the assembly System.Xml.Serialization.

To start, let's create a class that can store the information that we want to keep for each RSS:

C#
/* A simple class to store rss information. */
public class RssSource
{
    //Public Properties:
    [System.Xml.Serialization.XmlElement]
    public String Description { get; set; }
    [System.Xml.Serialization.XmlElement]
    public String Url { get; set; }
    //Constructors:
    public RssSource()
    {
    }
    public RssSource(String SourceDesc, String SourceUrl)
    {
        Description = SourceDesc;
        Url = SourceUrl;
    }
}

As you can see, it is a very simple class, has two public properties to store the RSS URL and a description and two constructors.

If you look at the properties of this class, you will see that both are decorated with the attribute System.Xml.Serialization.XmlElement, this serves for the XML serializer to become aware that each property represent an XML Element node.

Now, as we store more than one RSS feed in our file, we create another class, which will be serialized and also that it will have the functionality to add, delete, save and load our list of sources:

C#
/* A simple class to manage rss sources */
public class RssSources
{
    //Public List with all rss sources.
    [System.Xml.Serialization.XmlArray]
    public List<RssSource> Sources = new List<RssSource>();
    //Constructor.
    public RssSources()
    {
     
    }
    //Load rss sources saved to Isolated Storage.
    public bool LoadFromIso()
    {
        XmlSerializer Serializator = new XmlSerializer(typeof(RssSources));
        IsolatedStorageFile IsoFile = IsolatedStorageFile.GetUserStoreForApplication();
        IsolatedStorageFileStream Stream = IsoFile.OpenFile("Sources.rss", 
           FileMode.OpenOrCreate);
        try
        {
            RssSources DiskSources = (RssSources)Serializator.Deserialize(Stream);
            this.Sources = DiskSources.Sources;
            return true;
        }
        catch (Exception)
        {
            return false;
        }
        finally
        {
            Stream.Close();
            IsoFile.Dispose();
        }
    }
    //Add new rss source to the list.
    public bool AddSource(String Description, String Url)
    {
        try
        {
            Sources.Add(new RssSource(Description, Url));
            SaveToIso();
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
    //Delete rss source from the list.
    public bool DeleteSource(RssSource Item)
    {
        try
        {
            Sources.Remove(Item);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
    //Save current List of rss sources to Isolated Storage
    private bool SaveToIso()
    {
        XmlSerializer Serializator = new XmlSerializer(typeof(RssSources));
        IsolatedStorageFile IsoFile = IsolatedStorageFile.GetUserStoreForApplication();
        if (IsoFile.FileExists("Sources.rss"))
             {
                 IsoFile.DeleteFile("Sources.rss");
             }
        IsolatedStorageFileStream Stream = IsoFile.CreateFile("Sources.rss");
        try
        {
            Serializator.Serialize(Stream, this);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
        finally
        {
            Stream.Close();
            IsoFile.Dispose();
        }
    }
}

Well, this class exposes a list of type RssSource (the base class you created earlier), a parameterless constructor and four methods:

  • AddSource: Just add a new RssSource to the Sources list.
  • DeleteSource: Removes an existing Item from the List of sources.
  • SaveToIso: Using the XmlSerializer class, create a serializer the same type as our class, we get the IsolatedStore of our application and create a IsolatedSorageFileStream, and last serialize the content of our class to this file.
  • LoadFromIso: The reverse operation of SaveToIso method, we open a file with our class serialized and deserialized to obtain the RssSource list it contains.

If you examine the code, you see it is really simple and allows us to store information in a very simple and fast way, of course no substitute for a database, but for small pieces of data or physical persist the state of objects of our application is very useful.

Use of the WebClient Class

Well, we already have stored our RSS feed, but how do you get content from them? Well, very simple, using the WebClient class in Silverlight

This class allows you to download content in text format from a URI asynchronously, so the first thing to do is declare a method that responds to the WebClient class event DownloadStringCompleted:

C#
 private void DownloadComplete(object sender, DownloadStringCompletedEventArgs e)
{
    var client = sender as WebClient;
    if (client != null)
    {
        client.DownloadStringCompleted -= DownloadComplete;
    }
    if (e.Error != null)
    {
        throw e.Error;
    }
    if (e.Result != null)
    {
        //e.Result contains a String with the downloaded data.
    }
}

e.Result contains the text downloaded, in our case containing the different XML RSS news we've downloaded. In the sample project, I use LINQ to XML to get all the news and save them to a generic list.

Once we have defined the DownloadStringCompleted event handler, we only create the object and tell WebClient to download the RSS:

C#
WebClient client = new WebClient();
client.DownloadStringCompleted += DownloadComplete;
client.DownloadStringAsync(new Uri(RssUrl));

Use of the webBrowser Control to Load Dynamic Generated Content

The last step is to display the content of news, usually the content is in HTML format with images and other tags, so it is more appropriate to use the WebBrowser control to display content in a web page, for it only needs to add the head and body to our news and use the method NavigateToString of the WebBrowser control to display our HTML:

C#
webBrowser1.NavigateToString(
        "<html><head><meta name='viewport' " + 
 "content='width=480, user-scalable=yes'/>" + 
 "</head><body>" +
        (lstDetails.SelectedItem as RssFeed).Description +
        "</body></html>");

With this simple code, any text string can be displayed in the webbrowser control as if it were a web page.

And that's all. You can download the attached project to see all in action.

I hope you liked it. Happy coding! A big welcome to all and thanks for reading!

History

  • 02 July 2010 - First version
  • 15 July 2010 - Updated to the new Developer Tools Beta released from Microsoft some days ago:
    • Now using Microsoft.Phone assembly replacing Microsoft.Phone.Controls, Microsoft.Phone.Navigation, Microsoft.Phone.Shell and more...
    • The PhoneApplicationPage object now comes in the namespace Microsoft.Phone.Controls and not in the Microsoft.Phone.Navigation like in the CTP version
    • Deleted all UIElement.Effect references, not allowed in Beta version
    • The main page of our application now is defined in the file WMAppManifest.xml under Properties, in the section <Tasks><DefaultTask></DefaultTask></Tasks>
    • Posted new example code updated to Beta versión with all changes made.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Freelance Developer
Spain Spain
MVP Windows Platform Development 2014
MVP Windows Phone Development 2013
MVP Windows Phone Development 2012

Comments and Discussions

 
GeneralMy vote of 1 Pin
Mejamz2-Jan-12 13:37
Mejamz2-Jan-12 13:37 
QuestionDoesn't work in emulator Pin
Member 803732826-Jun-11 17:07
Member 803732826-Jun-11 17:07 
GeneralMy vote of 5 Pin
Digitalhour26-Jan-11 12:40
Digitalhour26-Jan-11 12:40 
GeneralErrors with latest RTM of tools Pin
PoorGreg28-Sep-10 9:22
PoorGreg28-Sep-10 9:22 
GeneralRe: Errors with latest RTM of tools Pin
Josué Yeray Julián Ferreiro28-Sep-10 9:32
Josué Yeray Julián Ferreiro28-Sep-10 9:32 
GeneralDoes not work :( Pin
Member 37603746-Aug-10 11:44
Member 37603746-Aug-10 11:44 
GeneralRe: Does not work :( Pin
Josué Yeray Julián Ferreiro8-Aug-10 20:44
Josué Yeray Julián Ferreiro8-Aug-10 20:44 
GeneralRe: Does not work :( Pin
Member 376037411-Aug-10 20:35
Member 376037411-Aug-10 20:35 
GeneralRe: Does not work :( Pin
Josué Yeray Julián Ferreiro11-Aug-10 21:16
Josué Yeray Julián Ferreiro11-Aug-10 21:16 
GeneralRe: Does not work :( Pin
Member 376037415-Aug-10 9:18
Member 376037415-Aug-10 9:18 
GeneralRe: Does not work :( Pin
Member 37603747-Sep-10 3:36
Member 37603747-Sep-10 3:36 
Any update?
QuestionUsing New Beta Version - Application Doesn't Do Anything Pin
Robert Galante28-Jul-10 0:57
Robert Galante28-Jul-10 0:57 
AnswerRe: Using New Beta Version - Application Doesn't Do Anything Pin
Josué Yeray Julián Ferreiro28-Jul-10 1:02
Josué Yeray Julián Ferreiro28-Jul-10 1:02 
GeneralRe: Using New Beta Version - Application Doesn't Do Anything Pin
rmgalante28-Jul-10 1:30
rmgalante28-Jul-10 1:30 
Generalerror accessing the iso storage Pin
Mike Fox15-Jul-10 9:21
Mike Fox15-Jul-10 9:21 
GeneralRe: error accessing the iso storage Pin
Josué Yeray Julián Ferreiro15-Jul-10 9:48
Josué Yeray Julián Ferreiro15-Jul-10 9:48 
GeneralPretty good stuff Pin
Md. Marufuzzaman2-Jul-10 19:45
professionalMd. Marufuzzaman2-Jul-10 19:45 
GeneralRe: Pretty good stuff Pin
Josué Yeray Julián Ferreiro2-Jul-10 23:32
Josué Yeray Julián Ferreiro2-Jul-10 23:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.