| Comments

Taking another cue from some great stuff Joel is doing, I liked his implementation of the ‘Leopard Screen Saver’ but wanted to make it more ‘real’ for me.  So I wired it up to my Flickr account.  Result here (using Silverlight Streaming):

I only had to change a few things.

First, in the Page_Loaded event, I removed the timer start function.  This was because with interacting with Flickr it was going to be async.  I didn’t want the timer to start until I knew the image collection was built.

My BuildCollection function now looks like this:

private void BuildCollection()
{
    // get Flickr NSID
    WebClient fu = new WebClient();
    fu.DownloadStringCompleted += new DownloadStringCompletedEventHandler(fu_DownloadStringCompleted);
    fu.DownloadStringAsync(new Uri(string.Format(FLICKR_USER_SEARCH, App.FlickrUser)));
}

This is a first call to get the NSID (internal Flickr user_id parameter) based on an initParam the user sends in.  The FLICKR_USER_SEARCH is just a const string parameter to the Flickr API rest call (with my API key in it) which looks like this:

const string FLICKR_USER_SEARCH = "http://api.flickr.com/services/rest/?method=flickr.urls.lookupuser
    &api_key=[yours]
    &url=http://flickr.com/photos/{0}";

I also use a FLICKR_USER_PHOTOS const which is like this:

const string FLICKR_USER_PHOTOS = "http://api.flickr.com/services/rest/?method=flickr.photos.search
    &user_id={0}
    &api_key=[yours]";

The completed event handler for the user search call looks like:

void fu_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    XDocument resp = XDocument.Parse(e.Result);

    string nsid = resp.Element("rsp").Element("user").Attribute("id").Value;

    WebClient p = new WebClient();
    p.DownloadStringCompleted += new DownloadStringCompletedEventHandler(p_DownloadStringCompleted);
    p.DownloadStringAsync(new Uri(string.Format(FLICKR_USER_PHOTOS, nsid)));
}

to retrieve the NSID.  With that I then start the search photos call to retrieve 42 photos.  The sample is a little hard-coded with count values, but this is just a quick change to see if it would work.  When the async operation to search the photos returns, I use some LINQ to mash them into FlickrImage object types using a custom class I put in my Silverlight application.

public class FlickrImage
{
    public string id { get; set; }
    public string farm { get; set; }
    public string server { get; set; }
    public string secret { get; set; }
    public string title { get; set; }
    public int tagid { get; set; }
    public string url
    {
        get
        {
            return string.Format("http://farm{0}.static.flickr.com/{1}/{2}_{3}_m.jpg",
               farm, server, id, secret);
        }
    }
}

and then the LINQ query:

XDocument xml = XDocument.Parse(e.Result);

var photos = from results in xml.Descendants("photo")
             select new FlickrImage
             {
                 id = results.Attribute("id").Value.ToString(),
                 farm = results.Attribute("farm").Value.ToString(),
                 server = results.Attribute("server").Value.ToString(),
                 secret = results.Attribute("secret").Value.ToString(),
                 title = results.Attribute("title").Value.ToString()
             };

Once I have these, I essentially moved the iteration code Joel had into a foreach loop for my images and then started the timer.

foreach (FlickrImage photo in photos)
{
    Uri imageUri = new Uri(photo.url, UriKind.Absolute);

    if (i <= 16)
    {
        Tile tile = new Tile();
        Media media = new Media(imageUri, true);
        tile.Media = media;

        if (col % 4 == 0)
        {
            row++;
            col = 0;
        }
        tile.SetValue(Grid.ColumnProperty, col.ToString());
        tile.SetValue(Grid.RowProperty, row.ToString());
        this.LayoutRoot.Children.Add(tile);

        col++;
        _tiles.Add(tile);
        _images.Add(media);

    }
    else
        _images.Add(new Media(imageUri, false));

    i++;
}

_timer.Start();

The result is the same visual sample Joel had, but using my live Flickr photos from my gallery.  This is made possible because Flickr has a) a REST api and b) a valid cross-domain policy file.  Both of these enable Silverlight to be a great client for consuming this data.  The visualization could be enhanced to provide mouse-over effects to zoom the picture I suppose, but I’ll get to that later.  Pretty fun that just a few changes (and none to XAML) enabled me to make this real for me.

The code for my changes is here but note you must have your own Flickr API key from their site.  I also implemented supporting an initParams value so you can pass in the Flickr user name dynamically. 

UPDATE: To use the initParams capability and display a badge for your Flickr account, you can use an <iframe> tag and point to http://silverlight.services.live.com/invoke/217/FlickrBadge/iframe.html?u=[yourflickrname] where the [yourflickrname] is the last part of your Flickr photos url.  For example if your account is at http://flickr.com/photos/uhoh_over than you would use http://silverlight.services.live.com/invoke/217/FlickrBadge/iframe.html?u=uhoh_over.

 

Please enjoy some of these other recent posts...

Comments