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:
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.
Can this same technique be used for regular Silverlight? I suppose you'd have to subclass the list box to get it to bind correctly to the IList...
"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.
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? ;-)
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.
Can u tell how to implement this virtualization in isolated storage insteed of cache.
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.
what if I use ObservableCollection instead of a list?
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.
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...
Having a basic list scoll is a key scenario for many applications. The Silverlight Windows Phone 7 list
Introduction One of the things I've been working on for a while is a "smart" ListBox implementation that
Does Virtualizing Data work fine with Wrap Panel?
I add this code, but i got a dead item exception.
Thanks for your help~