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.
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 :
- namespace BlogInto_win7
- {
- public class Feed
- {
- public int Id { get; set; }
- public string Title { get; set; }
- public string Link { get; set; }
- public string PubDate { get; set; }
- public string Author { get; set; }
- public string Description { get; set; }
- public string Votes { get; set; }
- }
- }
- namespace BlogInto_win7
- {
- /// <summary>
- /// Interaction logic for MainWindow.xaml
- /// </summary>
- public partial class MainWindow : Window
- {
- List<Feed> feeds;
- int currentFeed;
- private DispatcherTimer timer;
- private void Window_Loaded(object sender, RoutedEventArgs e)
- {
- this.Left = -5000;
- currentFeed = 0;
- browseFeed.IsEnabled = false;
- next.IsEnabled = false;
- previous.IsEnabled = false;
- LoadFeeds("http://www.bloginy.com/api/topFeeds/7RaLaXvDsZhBcYhS/bloginto");
- timer = new DispatcherTimer();
- timer.Interval = TimeSpan.FromSeconds(30);
- timer.Tick += timer_Tick;
- timer.Start();
- }
- private void timer_Tick(object sender, EventArgs e)
- {
- next.IsEnabled = false;
- browseFeed.IsEnabled = false;
- previous.IsEnabled = false;
- LoadFeeds("http://www.bloginy.com/api/topFeeds/7RaLaXvDsZhBcYhS/bloginto");
- }
- private void next_Click(object sender, EventArgs e)
- {
- currentFeed++;
- UpdateUI();
- if (currentFeed >= feeds.Count -1)
- {
- next.IsEnabled = false;
- }
- else
- previous.IsEnabled = true;
- }
- private void previous_Click(object sender, EventArgs e)
- {
- currentFeed--;
- UpdateUI();
- if (currentFeed < 1)
- previous.IsEnabled = false;
- next.IsEnabled = true;
- }
- private void browseFeed_Click(object sender, EventArgs e)
- {
- string url = "http://www.bloginy.com" + feeds[currentFeed].Link;
- System.Diagnostics.Process.Start(url);
- }
- private List<Feed> GetFeeds(string xml)
- {
- XDocument feeds = XDocument.Parse(xml);
- var result = feeds.Descendants("feed")
- .Select((f, index) => new Feed
- {
- Title = f.Element("title").Value.Replace("\n", ""),
- Link = f.Element("link").Value.Replace("\n", ""),
- PubDate = f.Element("pubdate").Value.Replace("\n", ""),
- Author = f.Element("author").Value.Replace("\n", ""),
- Description = f.Element("description").Value.Replace("\n", ""),
- Votes = f.Element("votes").Value.Replace("\n", ""),
- Id = index
- });
- return result.ToList();
- }
- void UpdateUI()
- {
- Feed feed = feeds[currentFeed];
- FeedTitle.Text = feed.Title;
- FeedAuthor.Text = "By: " + feed.Author;
- FeedDescription.Text = feed.Description;
- FeedDate.Text = feed.PubDate;
- FeedVotes.Text = feed.Votes;
- FeedRank.Text = (feed.Id + 1).ToString() + "/" + (feeds.Count).ToString();
- }
- void ResetUI()
- {
- FeedTitle.Text = "";
- FeedAuthor.Text = "";
- FeedDescription.Text = "";
- FeedDate.Text = "";
- FeedVotes.Text = "";
- FeedRank.Text = "";
- }
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.
- void LoadFeeds(string url)
- {
- BlogIntoTakbar.ProgressState = TaskbarItemProgressState.Indeterminate;
- WebClient client = new WebClient();
- client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted);
- client.DownloadProgressChanged +=new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
- client.DownloadDataAsync(new Uri(url));
- }
- private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
- {
- BlogIntoTakbar.ProgressState = TaskbarItemProgressState.Indeterminate;
- }
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.
- private void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
- {
- try
- {
- string result = System.Text.UTF8Encoding.UTF8.GetString(e.Result);
- feeds = GetFeeds(result);
- if (feeds != null)
- {
- currentFeed = 0;
- browseFeed.IsEnabled = true;
- next.IsEnabled = true;
- previous.IsEnabled = false;
- BlogIntoTakbar.ProgressState = TaskbarItemProgressState.None;
- NetworkError.Visibility = System.Windows.Visibility.Hidden;
- UpdateUI();
- }
- else
- throw new Exception();
- }
- catch
- {
- BlogIntoTakbar.ProgressState = TaskbarItemProgressState.Error;
- BlogIntoTakbar.ProgressValue = .9;
- browseFeed.IsEnabled = false;
- next.IsEnabled = false;
- previous.IsEnabled = false;
- NetworkError.Visibility = System.Windows.Visibility.Visible;
- ResetUI();
- }
- }