Silverlight for Windows Phone Performance team blog

This blog has been created by members of Silverlight for Windows Phone Performance team to convey best practices, tips and tricks for common performance issues on the phone. We'll discuss common pitfalls, platform bugs and any other issues we find

Silverlight for Windows Phone 7: ListBox Scroll Performance

Silverlight for Windows Phone 7: ListBox Scroll Performance

Rate This
  • Comments 17

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.

Simplify ListBox Item

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.

  • Ensure you have the item data template in a fixed sized container (grid).
  • Avoid/remove using complex converters, when the same information can be easily provided by the data object.
  • Avoid/remove nested structures, example listbox in a listbox item.
  • Strongly recommended to not use user control inside the data template.
  • Avoid/remove custom controls from the data template

Load the images in background

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.

Use Data Virtualization

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.

Do not use ListBox**

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.

Do not use Nested ListBox

If you have a need for nested list boxes, you should consider a solution similar to ListBoxGroupie

Other tips/approaches

  • HttpWebRequest must be used instead of WebClient. The reason for this is, there is a current platform issue where a request created via WebClient always returns on the UI thread, and again, we know that keeping the UI thread free is important.  Note: this is fixed in Mango, read about it here
  • When your list(in pivot/pano) is being populated, if you want to display a progress bar use the high performance progress bar
  • Sometimes you bind the list to an observable collection. In that case, Add items to the UI thread in batches every some miliseconds (example add 2 items every 20ms). This keeps the UI thread free for input from the user, avoiding stutters and delays, giving the perception of performance. This is much better than adding all 20 items in one go, drawing 20 items straight on the UI thread will keep it busy and wont take in the input from user, example the flick gesture for scroll. BingImageSearch is an example of one such application.
  • Peter has a good design example, where he stops loading the items if the list is scrolling. He elaborates about it in his blog on LazyListBox

Finally, we are incorporating all the feedback into the platform and your comments/feedback/questions are appreciated.

Thanks

Silverlight Windows Phone 7 Perfomance Team

Leave a Comment
  • Please add 4 and 1 and type the answer here:
  • Post
  • 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:

    Control

       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

    UserControl

       (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?

    Thanks

  • 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 ?

    Thanks

  • WHy avoid/remove custom controls from the data template ?

    Thanks

  • 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 ?

  • @Gabriel

    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.

    @Gergely Orosz

    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.

Page 1 of 2 (17 items) 12