CoreCLR's Blog

Silverlight 3: ListBox, ComboBox and AutoCompleteBox Performance

Posted by coreclr on September 26, 2009

One Silverlight 3 feature that is often overlooked is UI Virtualization. When a control supports UI Virtualization is only creates the UI elements that are actually visible on the screen.

Lets look at a simple example:

    <Grid x:Name="LayoutRoot">
        <ListBox x:Name="list"
            Margin="0,40,0,0"
            Width="240"
            Height="180"
            HorizontalAlignment="Left"
            VerticalAlignment="Top" />
        <Button Height="30"
                Width="200"
                VerticalAlignment="Top"
                Content="Load"
                HorizontalAlignment="Left"
                Click="OnClick"/>
    </Grid>

 

List<string> data = new List<string>();
public MainPage()
{
  InitializeComponent();
  for (int i = 0; i < 50000; i++)
  {
      data.Add(i.ToString());
  }
}

private void OnClick(object sender, RoutedEventArgs e)
{
   list.ItemsSource = data;
}

When the button is pressed, we set the ItemSource to a list with 50.000 strings. But performance is great because the control only creates UI elements for the visible elements and not for all 50.000 elements.

This works because in Silverlight 3, the ListBox by default use the VirtualizingStackPanel as its ItemsPanelTemplate.

If we change the ItemsPanelTemplate to a normal StackPanel, we don’t get UI Virtualization:

 <ListBox x:Name="list"
            Margin="0,40,0,0"
            Width="240"
            Height="180"
            HorizontalAlignment="Left"
            VerticalAlignment="Top">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>

Try this, and compare the performance.

AutoCompleteBox

Internally the AutoCompleteBox use a ListBox. This means that it also supports UI Virtualization. But there is one gotcha.

Try this:

<input:AutoCompleteBox x:Name="list"
   Margin="0,40,0,0"
   Width="240"
   IsTextCompletionEnabled="True"
   FilterMode="StartsWith"
   MinimumPrefixLength="0"
   MinimumPopulateDelay="200"
   HorizontalAlignment="Left"
   VerticalAlignment="Top">
</input:AutoCompleteBox>

When you type something in the box, it will take forever for it to open the dropdown.

The reason is that the ListBox in the AutoCompleteBox template don’t set an explicit MaxHeight, so it will just create UI elements for each item in its ItemSource.

This is a snippet from the template that illustrates this:

    <ListBox x:Name="Selector"
                Background="{TemplateBinding Background}"
                BorderThickness="0"
                Foreground="{TemplateBinding Foreground}"
                ItemTemplate="{TemplateBinding ItemTemplate}"
                ScrollViewer.HorizontalScrollBarVisibility="Auto"
                ScrollViewer.VerticalScrollBarVisibility="Auto"
                ItemContainerStyle="{TemplateBinding ItemContainerStyle}"/>

To fix this, we change to template to explicit set the MaxHeight:

<ListBox x:Name="Selector"
        MaxHeight="200"
        Background="{TemplateBinding Background}"
        BorderThickness="0"
        Foreground="{TemplateBinding Foreground}"
        ItemTemplate="{TemplateBinding ItemTemplate}"
        ScrollViewer.HorizontalScrollBarVisibility="Auto"
        ScrollViewer.VerticalScrollBarVisibility="Auto"
        ItemContainerStyle="{TemplateBinding ItemContainerStyle}"/>

A better approach would be to derive from the AutoCompleteBox class and make a dependency property. Then use DataBinding to connect the two properties.

The result is that same; The AutoCompleteBox now support UI Virtualization.

ComboBox

The ComboBox should also support UI Virtualization, but there seems to be a bug in the implementation. When opening the ComboBox, it seems that it creates UI elements for each item in its ItemSource. But when the dropdown is open, the scrolling is very fast. You can try this yourself:

 <ComboBox x:Name="list"
            Margin="0,40,0,0"
            Width="240"
            Height="180"
            HorizontalAlignment="Left"
            VerticalAlignment="Top">
            <ComboBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel />
                </ItemsPanelTemplate>
            </ComboBox.ItemsPanel>
        </ComboBox>

DataGrid

The DataGrid also supports UI Virtualization, and actually already did this i Silverlight 2.

TreeView

There is no UI Virtualization support for hierarchical data.

 

UI Virtualization has been in WPF for years, and its great to see it in Silverlight now.

The get more details, go to msdn or to Bea’s blog.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: