Introduction
In this earlier blog, I looked at how to use a ComboBox to display a list of all the system fonts, displaying each font name in its own font style.

I mentioned there that fonts are something of a special case, in that this collection of fonts is automatically cached for you after you first use it. The result is that when you run the application for the second and subsequent times there is minimal delay between the time the user clicks the ComboBox down arrow and the appearance of the list of fonts.
In this blog I want to look at the situation where you have a ComboBox that has a large number of other (possibly graphically complex) items to display.
Without the built-in caching that is available for fonts, you will often find that the display of large amounts of data in a ComboBox can be annoyingly slow. Furthermore, it will continue to be slow each time the ComboBox is recreated (although you can re-access the ComboBox and have shorter delays as long as you don't close the Window). However, if you close the Window that contains this ComboBox, then the whole display has to be rebuilt and the initial longer delay will reoccur.
The reason for the delay is that WPF creates the complete display for the ComboBox in advance, regardless of the fact that it might only display a tiny proportion of the total number of items. It is this initial unnecessary creation of visual content that causes the problem. Let's create a sample project to demonstrate this.
Display of Large Amount of Text
First, I'll create some fairly uninspiring demo data in the code-behind:
Private Sub Window2_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Dim DemoList As New List(Of String)
For i As Integer = 0 To 10000
DemoList.Add("This is ItemCollection # " & i.ToString)
Next
Me.DataContext = DemoList
End Sub
This simply creates 10,000 Strings, stores them in a List (Of String) and sets this List as the DataContext for the Window.
Next, in the markup for the Window, create a ComboBox that will use those Strings for its display of items:
<ComboBox Height="23" Margin="27,10,10,0" Name="ComboBox1"
VerticalAlignment="Top"
ItemsSource="{Binding}">
</ComboBox>
When you run this application, there will be noticeable delay before the list appears. As I mentioned above, when you click for a second and subsequent times, the delay is shorter but still exists. If you close this Window and then subsequently show it again, the long delay will reoccur.

Improving the Display Time
The quick fix for this issue is to insert a VirtualizingStackPanel into the template for the ComboBox. This panel has the ability to assess how many items can be displayed, based on the measurements of the ComboBox, and automatically creates the visuals for that limited number of items only.
An easy way to implement this is to create an ItemsPanelTemplate as a Resource and reference it in the ComboBox markup.
<Window.Resources>
<ItemsPanelTemplate x:Key="VSP">
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</Window.Resources>
<ComboBox Height="23" Margin="27,10,10,0" Name="ComboBox1"
VerticalAlignment="Top"
ItemsSource="{Binding}"
ItemsPanel="{StaticResource VSP}">
</ComboBox>
Specifically, the ItemsPanel property of the ComboBox is set to that ItemsPanelTemplate Resource.
If you prefer, you can include the VirtualizingStackPanel right in the ComboBox creation markup:
<ComboBox Height="23" Margin="27,10,10,0" Name="ComboBox1"
VerticalAlignment="Top"
ItemsSource="{Binding}"
>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
Personally, I like to try and keep as much of these kind of things as Resources as I can.
More Complex Items
If your display is more complex - maybe using a DataTemplate and including nested panels and some images in each item:
<DataTemplate x:Key="ImgAndText">
<StackPanel Orientation="Horizontal">
<Image Source="Timer.jpg" Height="89" Margin="3"></Image>
<StackPanel>
<Image Source="Stars.jpg" Width="152" Height="44" Stretch="None"></Image>
<TextBlock Text="{Binding}" Margin="2,15,2,2" ></TextBlock>
</StackPanel>
</StackPanel>
</DataTemplate>

then the delay can become very substantial indeed and you will certainly want to be sure to include a VirtualizingStackPanel in the markup for the ComboBox.