Take advantage of the new Windows 7 Taskbar #2 [Showcase : Bloginto7]

This is the part 2 of how to build a simple feed reader following the style of the Gmail Notifier Plus which uses basically the Windows 7 taskbar features.42001378_thumb
Part 1 was about the XAML part of the application, this part will show how to read the feeds asynchronously, how to change the ProgressBar and have an auto update features to read feeds.
First we need a prototype class to hold the feeds :

  1. namespace BlogInto_win7
  2. {
  3.     public class Feed
  4.     {
  5.         public int Id { get; set; }
  6.         public string Title { get; set; }
  7.         public string Link { get; set; }
  8.         public string PubDate { get; set; }
  9.         public string Author { get; set; }
  10.         public string Description { get; set; }
  11.         public string Votes { get; set; }
  12.     }
  13. }
Then we will need the following public variables to hold the feeds data, the current feeds shown and a timer for auto update.

  1. namespace BlogInto_win7
  2. {
  3.     /// <summary>
  4.     /// Interaction logic for MainWindow.xaml
  5.     /// </summary>
  6.     public partial class MainWindow : Window
  7.     {
  8.         List<Feed> feeds;
  9.         int currentFeed;
  10.         private DispatcherTimer timer;
On the Window_Loaded event, we hide the window so that it will be shown only in the Taskbar and not the desktop by setting its Left property to –5000, then we mark all the buttons disabled, we initialize the timer to tick every 30 seconds and we call LoadFeeds to download the feeds asynchronously.
  1. private void Window_Loaded(object sender, RoutedEventArgs e)
  2.         {
  3.             this.Left = -5000;
  4.             currentFeed = 0;
  5.             
  6.             browseFeed.IsEnabled = false;
  7.             next.IsEnabled = false;
  8.             previous.IsEnabled = false;
  9.  
  10.             LoadFeeds("http://www.bloginy.com/api/topFeeds/7RaLaXvDsZhBcYhS/bloginto");   
  11.  
  12.             timer = new DispatcherTimer();
  13.             timer.Interval = TimeSpan.FromSeconds(30);
  14.             timer.Tick += timer_Tick;
  15.  
  16.             timer.Start();
  17.         }
The timer_Tick method just disables the navigation buttons and calls LoadFeeds
  1. private void timer_Tick(object sender, EventArgs e)
  2. {
  3.     next.IsEnabled = false;
  4.     browseFeed.IsEnabled = false;
  5.     previous.IsEnabled = false;
  6.     LoadFeeds("http://www.bloginy.com/api/topFeeds/7RaLaXvDsZhBcYhS/bloginto");
  7. }
Then we handle the code for navigating between the feeds and when the browse button is clicked
  1. private void next_Click(object sender, EventArgs e)
  2. {
  3.     currentFeed++;
  4.     UpdateUI();
  5.     if (currentFeed >= feeds.Count -1)
  6.     {
  7.         next.IsEnabled = false;
  8.     }
  9.     else
  10.  
  11.     previous.IsEnabled = true;
  12. }
  13.  
  14. private void previous_Click(object sender, EventArgs e)
  15. {
  16.     currentFeed--;
  17.     UpdateUI();
  18.     if (currentFeed < 1)
  19.         previous.IsEnabled = false;
  20.     
  21.     next.IsEnabled = true;
  22. }
  23.  
  24. private void browseFeed_Click(object sender, EventArgs e)
  25. {
  26.     string url = "http://www.bloginy.com" + feeds[currentFeed].Link;
  27.     System.Diagnostics.Process.Start(url);
  28. }
The function GetFeeds takes an XML string and decodes it to a List<Feed> using Linq (so pretty)
  1. private List<Feed> GetFeeds(string xml)
  2.         {
  3.                 XDocument feeds = XDocument.Parse(xml);
  4.  
  5.                 var result = feeds.Descendants("feed")
  6.                     .Select((f, index) => new Feed
  7.                     {
  8.                         Title = f.Element("title").Value.Replace("\n", ""),
  9.                         Link = f.Element("link").Value.Replace("\n", ""),
  10.                         PubDate = f.Element("pubdate").Value.Replace("\n", ""),
  11.                         Author = f.Element("author").Value.Replace("\n", ""),
  12.                         Description = f.Element("description").Value.Replace("\n", ""),
  13.                         Votes = f.Element("votes").Value.Replace("\n", ""),
  14.                         Id = index
  15.                     });
  16.                 
  17.                 return result.ToList();
  18.         }
The UpdateUI method refreshes the UI to show the current feed designed by the global variable currentFeed, ResetUI clears any UI on the interface
  1. void UpdateUI()
  2. {
  3.     Feed feed = feeds[currentFeed];
  4.     FeedTitle.Text = feed.Title;
  5.     FeedAuthor.Text = "By: " + feed.Author;
  6.     FeedDescription.Text = feed.Description;
  7.     FeedDate.Text = feed.PubDate;
  8.     FeedVotes.Text = feed.Votes;
  9.     FeedRank.Text = (feed.Id + 1).ToString() + "/" + (feeds.Count).ToString();
  10. }
  11.  
  12. void ResetUI()
  13. {
  14.     FeedTitle.Text = "";
  15.     FeedAuthor.Text = "";
  16.     FeedDescription.Text = "";
  17.     FeedDate.Text = "";
  18.     FeedVotes.Text = "";
  19.     FeedRank.Text = "";
  20. }
The most important method is LoadFeeds which uses the WebClient class to load the XML feeds asynchronously, first it changes the ProgressBar status so that it indicates that the application is requesting new feeds from the web.
Then it initializes a WebClient object and attaching its DownloadDataCompleted and DownloadProgressChanged to 2 methods that handles the received XML asynchronously. client_DownloadProgressChanged is called when the WebClient is receiving data, client_DownloadDataCompleted is fired when the XML is ready to be parsed.
Then we call client.DownloadDataAsync(new Uri(url)); which downloads the XML asynchronously.
  1. void LoadFeeds(string url)
  2. {
  3.     BlogIntoTakbar.ProgressState = TaskbarItemProgressState.Indeterminate;
  4.  
  5.     WebClient client = new WebClient();
  6.     client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted);
  7.     client.DownloadProgressChanged +=new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
  8.  
  9.     client.DownloadDataAsync(new Uri(url));        
  10. }
The client_DownloadProgressChanged just sets the ProgressBar status to Indeterminate to indicate that it is always updating.
  1. private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
  2. {
  3.     BlogIntoTakbar.ProgressState = TaskbarItemProgressState.Indeterminate;
  4. }
The client_DownloadDataCompleted takes the DownloadDataCompletedEventArgs result and decodes it to string (from a Byte array) using the UTF8 encoding (you change this according to the feed you are receiving)
Then it refreshes the feeds collection by calling GetFeeds method. If the feeds load correctly then it sets the buttons to their active forms, changes the ProgressBar status to None otherwise it shows a Network error notification and changes the ProgressBar status to error to indicate a fail update.
  1. private void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
  2. {
  3.     try
  4.     {
  5.         string result = System.Text.UTF8Encoding.UTF8.GetString(e.Result);
  6.         
  7.         feeds = GetFeeds(result);
  8.         if (feeds != null)
  9.         {
  10.             currentFeed = 0;
  11.             browseFeed.IsEnabled = true;
  12.             next.IsEnabled = true;
  13.             previous.IsEnabled = false;
  14.             BlogIntoTakbar.ProgressState = TaskbarItemProgressState.None;
  15.             NetworkError.Visibility = System.Windows.Visibility.Hidden;
  16.             UpdateUI();
  17.         }
  18.         else
  19.             throw new Exception();
  20.     }
  21.     catch
  22.     {
  23.         BlogIntoTakbar.ProgressState = TaskbarItemProgressState.Error;
  24.         BlogIntoTakbar.ProgressValue = .9;
  25.         browseFeed.IsEnabled = false;
  26.         next.IsEnabled = false;
  27.         previous.IsEnabled = false;
  28.         NetworkError.Visibility = System.Windows.Visibility.Visible;
  29.         ResetUI();
  30.     }
  31. }
You can download the application and the source code from here http://web.martani.net/bloginto7

Posted in , , , , , , , , , . Bookmark the permalink. RSS feed for this post.

comments powered by Disqus

Swedish Greys - a WordPress theme from Nordic Themepark. Converted by LiteThemes.com.