Mobile Zone is brought to you in partnership with:

Jonathan creates software, mostly with C#, XAML, and HTML5/JS. He was awarded the Microsoft MVP in the "Client Application Development section in January 2011 Jon is a DZone MVB and is not an employee of DZone and has posted 23 posts at DZone. You can read more from them at their website. View Full User Profile

Windows Phone Features For the VirtualizingPanel

08.03.2012
| 2325 views |
  • submit to reddit
Virtualizing panels are involved when an application’s performance needs to be improved. It provide a base panel for virtualization of children elements inside it. Instead of creating all the UI element which are inside an ItemControls, only the one which need to be displayed are created. Because the process of creating these elements is intensive, the use of a VirtualizingPanel makes an item controls display faster.

The VirtualizingPanel comes with new features in WPF 4.5: two properties named ScrollUnit and CacheLength and virtualization on grouped data. In this post we will discover them in details.

This post is a part of a serie on WPF 4.5 new features.

WPF 4.0 behavior

To illustrate the new properties and their usage, we will create a demo project. It can be found on my Dropbox folder after registration.
This simple WPF application display a list of persons in a listbox with virtualization enabled. In the last part, we will group the persons by age.

A button is here to allow the user to add a lot of persons to the list (500 actually). When this operation is done, we calculate the elapsed render time and display it as a status bar message. This allow us to be sure that virtualization is really enabled. When it is, the load takes a dozen of ms and when it’s not, the operation takes a lot of time (7000 ms on my computer). This is one of the scenarii addressed by the virtualization.

foreach (var person in persons)
{
    Persons.Add(person);
}
var watch = new Stopwatch();
watch.Start();
//Wait for the rendering is finished..
Dispatcher.CurrentDispatcher.Invoke(new Action(() => { }),
      DispatcherPriority.Loaded, null);
 
watch.Stop();
 
Message = string.Format("Rendering took {0} ms.", watch.ElapsedMilliseconds);

Virtualization can be enabled and disabled via the VirtualizingStackPanel.IsVirtualizing attached property on a ListBox. By default it is but we force it anyway:

<ListBox ItemsSource="{Binding Persons}" Background="LightBlue"
        ItemTemplate="{StaticResource PersonDataTemplate}"
        ItemContainerStyle="{StaticResource ListBoxItemStyle}"
        VirtualizingStackPanel.IsVirtualizing="True"
        HorizontalContentAlignment="Stretch" />

To be able to see things clearly, I defined a style for the ListBoxItem which set their background to pink and I set the ListBox’s Background to blue:

CacheLength

The ViewPort is the visible aera of the virtualizing panel. With virtualization, only visible inside the viewport are really created in memory. Creating this items can be intensive and requires a noticeable time to be done. If so, the scrolling experience is not very good for the user because the reactivness of the application falls to nothing.

To reproduce this scenario, I have create an UserControl named TimeConsumingControl and I do something long in its constructor. Then I put it in the DataTemplate:

<DataTemplate x:Key="PersonDataTemplate"
        DataType="{x:Type local:Person}">
    <Grid>
        <!--This will take time to be instancied-->
        <local:TimeConsumingControl />
         
        <!--Rest of the data template-->
        ...
    </Grid>

In WPF 4.5 you can create a Cache of the item not displayed. When the virtualizing panel has finished the render of its items, it start the creation of the cache with a low priority. By doing so, when the user scroll into the list, he’ll not feel the slowness of the rendering because the items will already be created in the cache. Not that it’ll be true only for the one in the cache.

You can use two properties to configure the cache in WPF 4.5:

  1. CacheLength : The amount of space created in the cache before and after the ViewPort. The default value is 1,1.
  2. CacheLengthUnit : the unit of the ammount of space: Pixel, Item or Page. A page is defined by the size of the viewort. The default value is Page in the MSDN doc but it seems to be Item in my tests.

To demonstrate the benefit of their use is hard to do with a picture, but you can try the demo application to notice it.

Here is an example of their use in the the demo application XAML which define a cache of 2 pages before the viewPort and 3 after it:

<ListBox ItemsSource="{Binding Persons}"
        ItemTemplate="{StaticResource PersonDataTemplate}"
        ItemContainerStyle="{StaticResource ListBoxItemStyle}"
        VirtualizingStackPanel.IsVirtualizing="True"
        VirtualizingStackPanel.CacheLength="2,3"
        VirtualizingStackPanel.CacheLengthUnit="Page"/>

ScrollUnit

When virtualization is enabled, the scrolling can be perceived as little odd by the user because only full items are displayed. If an item does not fit entirely in the viewport defined by the ItemsControl then it’s not displayed.

In WPF 4.5, you can set the ScrollUnit property to one of these following values:

  • Item : The virtualizing panel can display blank aera because items that would require to be crop are not displayed. This is the default value (as in WPF 4.0).
  • Pixel : The virtualizing panel can display partial / cropped items as you may excepted it to be the default behavior.

So if we update the previous example to set this property to Pixel we’ll get the following XAML:

<ListBox ItemsSource="{Binding Persons}"
        ItemTemplate="{StaticResource PersonDataTemplate}"
        ItemContainerStyle="{StaticResource ListBoxItemStyle}"
        VirtualizingStackPanel.IsVirtualizing="True"
        VirtualizingStackPanel.ScrollUnit="Pixel" />

 

IsContainerVirtualizable

Finally, I found out reading the MSDN documentation a new attached property named IsContainerVirtualizable. It’s seems to be a property which tells the VirtualizingPanel if it should virtualize an item or not.

I tried to use it but I didn’t managed to. So I can’t tell you more on this except that it exist!

Published at DZone with permission of Jon Antoine, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)