Virtualizing Data in Windows Phone 7 Silverlight Applications

One of the cool features of lists in Silverlight is that they can "virtualize" the UI objects needed to render the list, reducing the amount of memory and CPU necessary to load large lists. For example, if you bind a ListBox to 1,000 items in Silverlight, it will only create ListBoxItems for the first few screens' worth of data (say, 30 objects) and create the UI for those based on the DataTemplate. The other 970 items do not get UI objects generated for them, which is a great saving of resources. As you scroll through the list, Silverlight recycles these container items and binds them against the rest of the data, giving the illusion that all the items are in the list at once.

One of the limitations of this in desktop Silverlight is that although the UI is virtualized, the data is not -- so although that 1,000 item list only has a fraction of the UI elements created, it needs all 1,000 of the data objects created and loaded, which can be a resource issue (long load times / high memory usage). This is because in desktop Silverlight the ListBox and other controls databind to IEnumerables, where the only option the control has is to enumerate the entire list to find out how large it is.

Enter Silverlight for Windows Phone, where we are more resource constrained than the desktop and can't afford to create all those data items like the desktop can. A simple solution is available for this, called data virtualization. The trigger for this is using an object that implementes IList (instead of just IEnumerable) as your ItemsSource. Using this more flexible interface, Silverlight can simply query the list's Count to find out how large it is and can request the individual items it needs to fill the virtualized UI objects via the indexer. This approach enables databounds lists in Windows Phone 7 to be essentially unlimited in size; the sample attached to this post is a list of 1,000,000 objects (yes, <Dr. Evil voice> one million objects! </Dr. Evil voice> ) that binds incredibly quickly, jumps to any point incredibly quickly, and scrolls like a champ. Try doing that on the desktop!

The sample also shows using a (very, very dumb) cache for storing even more objects than Silverlight virtualizes, in case you want to speed up certain operations. In this example, the cache is a dumb MRU cache that really only works for scrolling back through the list (if you scroll from 0 - 50 and then scroll back down to 0, a lot of the items will be returned as "cached items"). I don't recommend you actually use this cache, because it is dumb and slow, but you can see how the technique could be used to provide smart caching, or even predictive pre-loading of items, etc. to best balance memory usage and performance.

The only IList members you need to implement are:

  • Count, to return the actual number of items in your list;
  • IndexOf, to return the index of a specified item if it is in the list; and
  • this[] , to return the item at a given location (implementing set is not required)

Everything else can simply throw NotImplementedException, although of course it is nice to implement the other members if you play to use your data list in any context other than databinding.

VirtualizingDataTest.zip

Comments

  • Anonymous
    August 17, 2010
    The comment has been removed

  • Anonymous
    August 17, 2010
    "Try doing that on the desktop" Sure... Even better. If you have Silverlight 4, seehow Netflix Odata online catalog with 121,000+ itemsis data virtualized. Http://snurl.com/netflixdemo

  • Anonymous
    August 17, 2010
    That's a cool demo, but I was specifically talking about the built-in ListBox. There are always 3rd-party solutions that will do specific things much better. Are you porting to Windows Phone? ;-)

  • Anonymous
    August 17, 2010
    Peter, I can't announce anything yet, but the built-in listbox does leave a lot to be desired, I agree with you :) I forgot to say thanks for the article, I'm glad data virtualization is picking up in importance.

  • Anonymous
    September 01, 2010
    hi...     Can u tell how to implement this virtualization in isolated storage insteed of cache.

  • Anonymous
    September 01, 2010
    Jayabalaji, you need to implement the indexer to get items from IsoStore as they are needed. Most likely you will want to return placeholder items immediately and then bring in the data from IsoStore in an asynchronous fashion.

  • Anonymous
    September 08, 2010
    what if I use ObservableCollection instead of a list?

  • Anonymous
    September 09, 2010
    Hao: Best way is to try it! ObservableCollection itself exposes the correct properties but unless you are deriving your own custom class it won't virtualize for you.

  • Anonymous
    September 20, 2010
    this is a super simplistic scenario..it would be better if you were doing something little bit more insteresting in it like may be downloading some images from some share or doing db call to get the contents of list...all these contents you will have to get in async mode so where would you put the code to get new object..which could be an image or something like that...

  • Anonymous
    October 06, 2010
    Having a basic list scoll is a key scenario for many applications. The Silverlight Windows Phone 7 list

  • Anonymous
    October 06, 2010
    Having a basic list scoll is a key scenario for many applications. The Silverlight Windows Phone 7 list

  • Anonymous
    October 11, 2010
    Introduction One of the things I've been working on for a while is a "smart" ListBox implementation that

  • Anonymous
    October 11, 2010
    Introduction One of the things I've been working on for a while is a "smart" ListBox implementation that

  • Anonymous
    October 12, 2010
    Introduction One of the things I've been working on for a while is a "smart" ListBox implementation that

  • Anonymous
    October 13, 2010
    Hi~ Does Virtualizing Data work fine with Wrap Panel? <ListBox.ItemsPanel>                <ItemsPanelTemplate>                    <controlsToolkit:WrapPanel                                    ItemWidth="150"></controlsToolkit:WrapPanel>                </ItemsPanelTemplate> </ListBox.ItemsPanel> I add this code, but i got a dead item exception. Thanks for your help~

  • Anonymous
    October 13, 2010
    Hi Eric, if the WrapPanel derives from VirtualizingPanel it should work, otherwise it won't. It's an interesting feature request though if indeed it doesn't currently work.

  • Anonymous
    October 14, 2010
    Having a basic list scoll is a key scenario for many applications. The Silverlight Windows Phone 7 list