Having a basic list scoll is a key scenario for many applications. The Silverlight Windows Phone 7 list box control makes it easy to bind data and get the performance benefits of UI container virtualization. However, in order to get these free performance benefits you need to be careful about how you use it.
Here are some tips on how to tweek your list box scroll performance.
Listbox's VirtualizingStackPanel (VSP), calculates the height of items currently in the view and buffers the UI containers for a screens worth of items above and below what is currently in the view. This works great if the items are of fixed size. If you change the size of the items, the UI virtualization breaks and you don't get any performance benefits.
If you have refered to the performance document, you will know the importance of keeping the UI thread free for better responsiveness to handle input. This means that if you load the images on the UI thread, an input like flick might be lost. David talks about how to move the image loading to a single background thread in his blog LowProfileImageLoader.
When using ListBox, UI is virtualized, the data is not -- so although a 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. Peter has a solution to this in his post on Data Virtualization.
If your application demands variable height items, but the number of items is managable enough to keep in memory. You should consider a solution without list box, example: David Anson talks about how to use StackPanel instead of a ListBox in his post on DefferedLoadListBox from Delay in order to get good performance from a scenario that's pretty common for social media applications: a scrolling list of entries with a picture and a brief bit of text. Its easy to try it out for your application.
If you have a need for nested list boxes, you should consider a solution similar to ListBoxGroupie
Finally, we are incorporating all the feedback into the platform and your comments/feedback/questions are appreciated.
Silverlight Windows Phone 7 Perfomance Team
Why shouldn't you use a usercontrol in a data template?
Good question Robbie, in short, "UserControls with XAML don’t cache their XAML so it’ll be read as a resource from the assembly on each instantiation."
Heres more details on it:
Control Templates are cached to the extent that their XAML is saved as a string by the ControlTemplate. It is parsed and instantiated at layout time. UserControls that have accompanying XAML do not cache their XAML, but this will be read as a resource from the assembly, and parsed. This happens when the UserControl is created. So the difference here is that with a Control, you bypass the need to load a resource stream to get the XAML each time. With a Control, there is an initial hit to load and parse generic.xaml, but that happens only once. WHen the built-in style is applied, the Template property will be set.
For each instantiation:
Read/parse Generic.xaml (one time per assembly). ControlTemplates are saved as strings
Look up built-in style in ResourceDictionary
Apply built-in style
(Measure pass) ControlTemplate's XAML is parsed
(in ctor) InitializeComponent is called, XAML loaded as resource, and parsed
Hence, the usercontrol takes a perf hit.
Could you elaborate on the use of HTTPWebRequest over WebClient?
I've used WebClient extensively and didn't see any perf problems on a device, can I continue to use it? Are things likely to break when you fix the issue?
Will, Thank you for clarifying your concerns.
Changes we make to WebClient will not break backward compatibility on applications already using it.
Only reason we recommend HttpWebRequest over WebClient is the response to WebClient request comes on UI thread even though it was created on background thread. And if you have an image being downloaded on the UI thread, it will block the responsiveness of your application.
However, if you are noticing that your activity on the UI thread isn’t impacting the performance, then great ! You already have a good performing app.
Thanks for the clarification :)
WHy avoid/remove custom controls from the data template ?
In my opinion the ListBox is one of the worst controls in terms of performance on WP7... even with 300 text items it starts to lag when scrolling fast up and down and a list with 200 items with pictures took about 2 seconds to load with all of these tricks implemented in the article. This is really annoying... this loading could be tolerated once, but on a list - detail application when the user navigates back to the list, loading happens again.
My solution was to limit the number of ListBox items to 30 and add paging after that - this was the *only* solution* I could get a decent performance out of on a developer device.
Personally I think this ListBox issue should be addressed by the WP7 team as this is a common control that is used in almost all applications and consumers immediately notice its slowness. See Endgadget's review: even they're complaining about how sluggish and unresponsive Seesmic's and other 3rd party app's scrolling is, compared to the native application's scrolling: www.engadget.com/.../windows-phone-7-review Not to mention that all iPhone apps scroll through 500 items in a list with images and background set for each item like a charm....
I have a question: are (some of) these principles applicable also to other Silverlight 4 WP7 containers such as StackPanel, WrapPanel or ScrollViewer ?
Listbox uses VirtualizingStackPanel, so many of these principles apply to VSP, which recycles the item-containers.
If you look at the other blogpost recommended in this one, they are ListBoxVariant solutions using StackPanel.
Simple things like loading images on background thread apply to all containers.
There are a lot of factors impacting the listbox performance. Its difficult to have a generic solution that caters to everyones scenario and maintains compatibility with Silverlight for Desktop.
Given this, we have definitely taken into account all the feedback(criticism) and looked deeper into solving the problem from platform's prospective.
Please refer to the MIX11 videos talking about SLM performance improvements focusing specifically on ListBox. Also, SLMPerf will have more blogposts on these new improvements soon.
Again, thank you for the feedback.
Please refer to the post on Mango Improvements for listbox blogs.msdn.com/.../listbox-scrollviewer-performance-improvement-for-mango-and-how-it-impacts-your-existing-application.aspx
If I have very hung collection(for example:10000), I use list.itemsource = list. It will be block very long time. How can I do to improve this issue.
I have listbox binded content (observable collection, which have images too)
On async request i populate collection by clearing and adding new content, at that time flicker occurs and seems it involved whole pivot page, on which i have listbox.
Any possibility to use vitrualization trough IList when I use observable collection for my ListBox?
Or just use the batch approach mentioned above (adding 2 items every 20 ms to the UI thread)
David Anson's DeferredLoadListBox does not work for variable height items. Needs correction.