Search EggHeadCafe's Job Board
EggHeadCafe Silverlight WPF ASP.NET VB.NET C# Excel SQL Server SharePoint
search
MicrosoftArticlesForumsFAQs
C# .NET
VB.NET
Visual Studio .NET
ADO.NET
Xml / Xslt
VB 6.0
.NET CF
GDI+
LINQ
Deployment
Security
FoxPro
Silverlight / WPF
Entity Framework
RIA Services

WebArticlesForumsFAQs
JavaScript
ASP
ASP.NET
WCF

DatabasesArticlesForumsFAQs
SQL Server
Access
Oracle
MySQL
Other Databases

OfficeArticlesForumsFAQs
Excel
Word
Powerpoint
Outlook
Publisher
Money

Non-MicrosoftArticlesForumsFAQs
NHibernate
Perl
PHP
Ruby
Java
Linux / Unix
Apple
Open Source

Operating SysArticlesForumsFAQs
Windows 7
Windows Server
Windows Vista
Windows XP
Windows Update
MAC
Linux / UNIX

Server PlatformsArticlesForumsFAQs
BizTalk
Site Server
Exhange Server
IIS

Graphic DesignArticlesForumsFAQs
Macromedia Flash
Adobe PhotoShop
Expression Blend
Expression Design
Expression Web

OtherArticlesForumsFAQs
Lounge
Subversion / CVS
Ask Dr. Dotnetsky
Active Directory
Networking
Uninstall Virus
Job Openings
Product Reviews
Search Engines
Resumes

 

Silverlight 3: Displaying and Charting with TwitterCounter


By Peter Bromberg
Printer Friendly Version
View My Articles
93 Views
    

A Silverlight application that displays the TwitterCounter user's stats and chart.


I stumbled on to TwitterCounter.com recently and like any typical narcissistic geek, I put my username in there to see their stats on my account. One of the first things I noticed is the nice chart that shows a timeline of your followers counts. Being an ex financial consultant, I love charts. The next thing I noticed is that they have a very easy - to - use API that will return all this data in XML format, which makes is pretty easy to turn into objects that can be bound to Silverlight fields, and the series of chart data can be bound to a Silverlight chart.

So, I set out to have some fun and test my skills with this little Silverlight 3 "TwitterCounter" display app.

When I first checked their API, I saw that there is a crossdomain.xml file present at the root of the site, but for some reason this wasn't working for me, so I resorted to using my ClientAccess.ashx handler to proxy the requests.  In order to have a container for the returned data, I needed a couple of POCO classes:

using System.Collections.Generic;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace TwitterCounter
{
    public class TwitterCounter
    {
      public string User_id { get; set; }
        public string User_name { get; set; }
        public string Followers_Current { get; set; }
        public DateTime? Date_updated { get; set; }
        public string Url { get; set; }
        public string Avatar {get; set;}
        public string Follow_since { get; set; }
        public string Started_Followers { get; set; }
        public string Growth_since { get; set; }
        public string Average_growth { get; set; }
        public string Tomorrow { get; set; }
        public string Next_month { get; set; }
        public string Followers_yesterday { get; set; }
        public string Followers2wAgo { get; set; }
        public string GrowthSince2w { get; set; }
        public string AverageGrowth2w { get; set; }
        public string Tomorrow2w { get; set; }
        public string NextMonth2w { get; set; }
        public List<FollowersPerDate> FollowersPerDate { get; set; }


    }

    public class FollowersPerDate
    {
        public DateTime Date { get; set; }
        public int Number { get; set; }
    }
}
Then, I needed a mechanism to download the data by concatenating  the username into the API Url, and process the data:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.DataVisualization.Charting;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Xml.Linq;

namespace TwitterCounter
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void ButtonSubmit_Click(object sender, RoutedEventArgs e)
        {
            WebClient wc = new WebClient();
            string url = App.TwitterCounterUrl1 + this.txtUserName.Text + App.TwitterCounterUrl2;
            url = App.ConvertUrl(url);
            wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
            wc.DownloadStringAsync(new Uri(url));
        }

        void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if(e.Error!=null)
            {
                MessageBox.Show(e.Error.ToString() );
                return;
            }
            XElement xel = XElement.Parse(e.Result);
            TwitterCounter tc = new TwitterCounter();
            tc.Avatar = App.AvatarUrl + xel.Element("avatar").Value;
            tc.Average_growth = xel.Element("average_growth").Value;
            tc.User_id = xel.Element("user_id").Value;
            tc.User_name = xel.Element("user_name").Value;
            tc.Followers_Current = xel.Element("followers_current").Value;
            tc.Date_updated = DateTime.Parse(xel.Element("date_updated").Value);
            tc.Url = xel.Element("url").Value;
            tc.Follow_since = xel.Element("follow_since") == null ? "" : xel.Element("follow_since").Value;
            tc.Started_Followers = xel.Element("started_followers").Value;
            tc.Growth_since = xel.Element("growth_since").Value;
            tc.Average_growth = xel.Element("average_growth").Value;
            tc.Tomorrow = xel.Element("tomorrow").Value;
            tc.Next_month = xel.Element("next_month").Value;
            tc.Followers_yesterday = xel.Element("followers_yesterday").Value;
            tc.Followers2wAgo = xel.Element("followers_2w_ago").Value;
            tc.GrowthSince2w = xel.Element("growth_since_2w").Value;
            tc.AverageGrowth2w = xel.Element("average_growth_2w").Value;
            tc.Tomorrow2w = xel.Element("tomorrow_2w").Value;
            tc.NextMonth2w = xel.Element("next_month_2w").Value;
            tc.FollowersPerDate = new List<FollowersPerDate>();

            var perdates = xel.Element("followersperdate").Descendants();
            foreach(var elem in  perdates)
            {
                tc.FollowersPerDate.Add(new FollowersPerDate()
                      {Date = DateTime.Parse(elem.Name.ToString().Replace("date", "")), Number = Convert.ToInt32(elem.Value)});
            }
            this.LayoutRoot.DataContext = tc;
            LineSeries myLineSeries = LineChart.Series[0] as LineSeries; 
            if (myLineSeries != null) { myLineSeries.ItemsSource = getData(tc.FollowersPerDate ); }
        }

        private  KeyValuePair<DateTime, int>[] getData( List<FollowersPerDate> lfpd )       
        {    
            KeyValuePair<DateTime, int>[] dataArray = new KeyValuePair<DateTime, int>[lfpd.Count];
            int i = 0;
            foreach(var followerperdate in lfpd)
            {
                dataArray[i] = new KeyValuePair<DateTime, int>(followerperdate.Date , followerperdate.Number );
                i++;
            }
            return dataArray;     
        }

        private void Url_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Browser.HtmlPage.Window.Navigate(
                new Uri(this.Url.Content.ToString()));
        }
    }
}
The result looks like this:



You can download the complete Visual Studio 2008 Silverlight 3 solution here.

Biography - Peter Bromberg
Peter Bromberg is a C# MVP, MCP, and .NET expert who has worked in banking, financial and telephony for over 20 years. Pete focuses exclusively on the .NET Platform, and currently develops SOA and other .NET applications for a Fortune 500 clientele. Peter enjoys producing digital photo collage with Maya,playing jazz flute, the beach, and fine wines. You can view Peter's UnBlog and IttyUrl sites.
Please post questions at forums, not via email!

button
Article Discussion: Silverlight 3: Displaying and Charting with TwitterCounter
Peter Bromberg posted at Wednesday, June 17, 2009 10:45 AM
Original Article