Building an RSS Reader for Windows Phone 7

I noticed that Sam over on the Silverlight Show posted about a Windows Phone 7 Series RSS Reader which uses the WebBrowser control to render the content. I figured that whilst that was a neat approach to displaying content an alternative would be to parse the feed, extract the content and display using a combination of TextBlock, Run and LineBreak elements. The following screenshot shows my blog being viewed using such an approach.

image 
Here’s the core code that makes this all happen. It uses the SyndicationFeed class to extract the posts – in my case I’ve just embedded the feed source as a text resource file (hence var rss = RssResources.BlogPosts, where RssResources is a reference to the designer generated wrapper). I then loop through looking for html tags, specifically end of paragraphs and images. I’m sure there’s a more elegant way of doing this but for demo purposes this did the trick.

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            // Load RSS into a feed
            var rss = RssResources.BlogPosts;
            using(var strm = new System.IO.StringReader(rss))
            using(var reader = System.Xml.XmlReader.Create(strm))
            {
                var feed = System.ServiceModel.Syndication.SyndicationFeed.Load(reader);
                // Regular expression to look for html tags
                var tagFinder = new System.Text.RegularExpressions.Regex("<(.|n)+?>", System.Text.RegularExpressions.RegexOptions.IgnoreCase);

                // Create the initial textblock
                var txt = new TextBlock() { TextWrapping = TextWrapping.Wrap };
                this.stackPanel1.Children.Add(txt);
                foreach (var item in feed.Items)
                {
                    // Add a title
                    txt.Inlines.Add(new Run() { FontWeight = FontWeights.Bold, Text = item.Title.Text });
                    txt.Inlines.Add(new LineBreak());
                    var itemText = item.Summary.Text;
                    var match = tagFinder.Match(itemText);
                    var startidx = 0;
                    while (match.Index >= 0 && match.Length > 0)
                    {
                        if (match.Value == "</p>" || match.Value == "<p />" || match.Value == "<br />")
                        {
                            // Found the end of a paragraph, so append this text to the textblock
                            var text = itemText.Substring(startidx, match.Index – startidx);
                            text = tagFinder.Replace(text, "");
                            txt.Inlines.Add(text);
                        }
                        else if (match.Value.Contains("<img"))
                        {
                            // Add the text up to the image tag
                            var text = itemText.Substring(startidx, match.Index – startidx);
                            text = tagFinder.Replace(text, "");
                            txt.Inlines.Add(text);

                            // Locate the url of the image
                            var idx = match.Value.IndexOf("src");
                            var url = match.Value.Substring(idx + 5, match.Value.IndexOf(""", idx + 6) – (idx + 5));

                            // Create an image and add to stackpanel
                            var img = new Image() { Source = new BitmapImage(new Uri(url)) };
                            img.Width = this.scrollViewer1.ActualWidth / 2;
                            img.Stretch = Stretch.UniformToFill;
                            this.stackPanel1.Children.Add(img);

                            // Create a new textblock and add to stackpanel
                            txt = new TextBlock() { TextWrapping = TextWrapping.Wrap };
                            this.stackPanel1.Children.Add(txt);
                        }

                        // Look for the next tag
                        startidx = match.Index + match.Length;
                        match = tagFinder.Match(itemText, match.Index + 1);

                    }
                    // Add the remaining text
                    txt.Inlines.Add(itemText.Substring(startidx));

                    // Add some space before the next post
                    txt.Inlines.Add(new LineBreak());
                    txt.Inlines.Add(new LineBreak());
                }
            }
        }

Leave a comment