Deakin Microsoft Student Partners
Get Microsoft Silverlight


Silverlight Month: Silverlight 102

August 18th, 2009, Paul , Tags: ,

What you’ll need

Okay okay, it hasn’t exactly been all within the same month, but with exams and illness, I haven’t had time to dive into it! Unlike last time, I’m not going through every single step, just the interesting snippets. Because of that, there isn’t a starter kit, just the final project.

imageClick to view the demo!

Silverlight 3 bringing in more awesome

You may notice that I am now using Silverlight 3. Silverlight 3 is even closer to WPF than before and it solves some of the "hackery" in TastyLibrary. In the first post, I used LINQ to rebind the ItemSource every time you click a new category. Thanks to the filtering capabilities introduced in Silverlight 3, we can "do it right" by filtering the CollectionViewSource.


private void lstCategories_SelectionChanged(object sender,     System.Windows.Controls.SelectionChangedEventArgs e)
{
    cvsItems.Filter += new FilterEventHandler(cvsItems_Filter);
}
 
void cvsItems_Filter(object sender, FilterEventArgs e)
{
    if (lstCategories.SelectedIndex >= 0)
    {
        if (((Item)(e.Item)).Category == ((Category)lstCategories.SelectedItem))
            e.Accepted = true;
        else
            e.Accepted = false;
    }
    else 
        e.Accepted = true;
}

Functionally, it appears to be the same… until you start adding more data. When you’re setting the ItemSource to a LINQ query, it doesn’t automatically update when new items are added into the base collection but when you are filtering every item has to pass through the filtering method even the new items that are added.

Apart from filtering, Silverlight 3 now has hardware accelerated effects, such as drop shadows or whatever you can build with pixel shaders! While it sounds gimmicky, drop shadows can help to create a much more refined UI. I’ve chosen to add this to various Grid’s in XAML:

<Grid.Effect>
    <DropShadowEffect BlurRadius="16" Direction="238" ShadowDepth="0"/>
</Grid.Effect>

(Don’t worry, there are plenty of other new features in Silverlight 3, but those are all I’m using)

Adding more data

In the last episode, we created a very basic clone of Delicious Library. Our version let you view a "bookshelf" of a set of albums, DVDs or games, the only problem was it was a fixed set of data. That makes it not particularly useful, because you’d have to manually edit the XML files whenever you wanted to add or remove an item. For a data source, I’d recommend and I have used Amazon simply because they are one of the (if not the largest) online stores and they provide a nice API.

If we were creating a desktop application, we could quiet easily use the SOAP interface and auto-generate the classes from the WSDL. However, Silverlight has security restrictions on the way it can interact with websites. If you are interacting with a web service on the same domain there are no restrictions, but interacting with services on other domains requires the domain to implement a cross domain policy file (and it must permit your application). Flash has similar restrictions on it. A common work around to this ‘problem’ is to use a proxy on your own server which does all the interaction with the service, but it’s messy, particularly when in this case, the Amazon Advertising (formerly ECS) REST/XML API has a cross domain policy file that works properly with Silverlight.

The SignedRequestHelper is provided from Amazon’s C# example of connecting to their API, while the Amazon namespace is a small helper library I’ve made to make it easier to choose various parameters/methods when interacting with Amazon’s API.

private void Search(string Keyword, string SearchIndex)
{
    SignedRequestHelper helper = new SignedRequestHelper(amazonAccessKey,       amazonSecretKey, Amazon.Destinations.US);
 
    IDictionary<string, string> requestParams = new Dictionary<string, String>();
    requestParams["Service"] = "AWSECommerceService";
    requestParams["Version"] = "2009-03-31";
    requestParams["Operation"] = Amazon.Operation.ItemSearch;
    requestParams["Keywords"] = HttpUtility.UrlEncode(Keyword);
    requestParams["SearchIndex"] = SearchIndex;
    requestParams["ResponseGroup"] = Amazon.ResponseGroup.Medium;
 
    string requestUrl = helper.Sign(requestParams);
 
    WebClient req = new WebClient();
    req.DownloadStringCompleted += new DownloadStringCompletedEventHandler      (req_DownloadStringCompleted);
    req.DownloadStringAsync(new Uri(requestUrl));
}

Searching for items is easy! Wait, hang on, where is the response? Silverlight requires network interactions to be asynchronous so that the calling thread (ie, the UI) doesn’t hang which would result in the entire browser locking up! (unless it separates tabs/plugins into threads like Google Chrome)

The response…

private void req_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    XNamespace ns = NAMESPACE;
    XDocument results = XDocument.Parse(e.Result);
 
    var resultItems = from i in results.Descendants(ns + "Item")
                select i;
 
    foreach (var item in resultItems)
    {
        try
        {
            var img = (from i in item.Element(ns + "ImageSets").Elements(ns + "ImageSet")
                       where i.Attribute("Category").Value == "primary"
                       select i).First().Element(ns + "MediumImage").Element(ns + "URL").Value;
        
            Item temp = new Item()
                    {
                        Name = item.Element(ns + "ItemAttributes").Element(ns + "Title").Value,
                        Image = img
                    };
            if (cbCategory.SelectedItem == cbiGames)
                temp.Category = catList["Games"];
            else if (cbCategory.SelectedItem == cbiDVDs)
                temp.Category = catList["DVDs"];
            else if (cbCategory.SelectedItem == cbiMusic)
                temp.Category = catList["Music"];
 
            lstSearchItems.Items.Add(temp);
        }
        catch (Exception ex)
        {
 
        }
    }
}

To parse the response I’ve used Linq-to-XML, created my new Item, and then inserted into the listbox containing all the search items.

This post shows off some basic Silverlight 3 features as well as interaction with web services uses Silverlight. Next post – interacting with persisting data!

Checkout the demo or grab the full source code


No Comments »