advanced web statistics

Hacking Silverlight, ObservableCollections, & Scarface

8/21/2008 10:18:26 PM

In working with Silverlight lately I've found that there's not a lot of documentation, especially for more complex functionality.  More times than not I find myself sort of scratching my head and wondering if the solution provided is really the best way to accomplish a certain task.

Let's say you're creating an application that serves up articles (i.e. for a library search application).  You have an ItemsControl that uses a article item control as it's DataTemplate. The ItemsSource of this ItemsControl is an ObservableCollection<T> of type, I don't know; SearchResult.  The DataContext for your ItemsControl is, you guessed it; SearchResult.

Now say you have, above your search results, a little panel that provides filtering.  The filters are List<T> -bound that expand when clicked (and roll up when done). In keeping with our library search application let's pretend the filters are by year (Last Week, Last Month, Last Year, Last 2 Years, etc....) and by topic (Sociology, Psychology, Political Science, Computer Science, etc..).  The year filter allows you to select only one (the selection of a listitem triggers the list to hide and the listing of articles below to refresh).  The user can select any number of topics.  Each listitem in the topic filter has an overlay that provides button functionality such as "SELECT / DESELECT, CLEAR ALL, DONE".  When you select an item, it highlights that row.  DESELECT unhighlights the row.  DONE means you are done selecting and rolls (hides) the list back up.  CLEAR ALL is the problem child.  Behind the scenes we are storing the id for the listitem in a List<T>.  We have easy access to these on MouseLeftButtonUp due to our DataContext being set earlier.  Clicking done will trigger the enumeration of this list to build our query and then that is sent to a web service.  There is a subscription to the ArticleRefresh trigger and the ItemsControl listing is updated. Easy.

The issue is the unhighlighting of all the listitems in the topic list upon clicking CLEAR ALL.  That sounds really easy (and it may very well be!) but I haven't seemed to figure out an efficient way to do this.

In ASP.NET it was extremely easy to enumerate all the controls from within, let's say a Repeater.  You have in your ItemTemplate a control that you want to repeat.  You could write a little bit of code to enumerate every RepeaterItem and alter the display of certain text and controls within that Repeater.  It's extremely easy.

In Silverlight you don't have that luxury.  Well, you're supposed to have an easier way of doing business but I haven't yet found it.  By the way, I'm talking about Silverlight 2 Beta 2. 

My first attempt at this was to create a Converter that sets the IsSelected property based on the presence of the topic's id in the List<T> it is bound to.  I get a BAD_PROPERTY_VALUE error when that is attempted.

The next attempt was creating an event handler for the Loaded event of my topic filter control that will cast the sender to the filter object, check to see if the id of the objects DataContext is contained in the List<T>.  If it is, highlight, else, no highlight.  This works the first time the application is loaded but not on subsequent list views.  Reason being the use of the ObservableCollection<T>.  The collection itself hasn't changed, so no rebinding needs to occur.  This is probably a good thing.  What if the collection had 100's, 1000's of items?  Makes for quick UI responsiveness.

The only way I have found to accomplish this is instantiating an IEnumerable object, setting its collection to that of the ObservableCollection<T> that the filter list is bound to (public property), then setting said public property to this IEnumerable object that is, in a sense, the same exact thing.  This way the collection has changed (sort of), and the CollectionChanged event now gets fired.  The list is re-bound and we start from scratch with no highlighted rows.

That seems like kind of a hack to me.  Anyone else care to chime in?

I'll try to get a code sample but this is one of those things that I had to voice out first.  I hope it's not too hard to follow.   For some reason today I had Paul Engemann's "Push it to the Limit" in my head while trying out all sorts of different ways of accomplishing this task.  I kind of laughed to myself at the idea of a programming montage set to this song (kind of like in the South Park episode with the skiing contest. And, of course, Scarface).

For the first time EVER on this blog, musical accompaniment:

Silverlight

kick it on DotNetKicks.com

Comments


nice title :)

Posted by: David kelley | 9/12/2008 11:34:30 AM

I strive for excellence! Your URL isn`t too shabby either.

Posted by: Will Asrari | 9/12/2008 11:47:53 AM

Leave a Comment

   

  Enter the text to proceed!