Looping ComboBox

Let’s start with a small UI issue I noticed some time ago in some of my Windows Store App projects:

When opening a simple ComboBox control and scrolling through its items, the list of items is repeated continuously – when reaching the last item, the list simply continues with displaying the first one again, and so on.

It seams that the default ComboBox control of the Windows Store framework is displayed differently in touch mode than when using mouse interaction. While the latter is similar to the “traditional” look and feel we are used to from desktop applications featuring a drop-down list of all ComboBox items, the touch mode displays the items floating above and below the actual UI control, and when scrolling it loops through the items, as described above.

The reason is that in “touch mode” the ComboBox control uses the special CarouselPanel to layout its content items. The CarouselPanel works similar to a StackPanel with the Orientation attribute set to “Vertical”, except for that is loops through its items: After the last item in the list, an empty placeholder is shown, then it continues with the first list item.

(To be exact, the CarouselPanel should rather be compared to the VirtualizingStackPanel, since both virtualize their content to improve performance when working with large item collections – though you will, in contrast to a StackPanel, probably never use a stand-alone CarouselPanel for laying out components on a page, since it can be used only within an ItemsControl and is therefore designed for use only as ItemsPanelTemplate.)

However, let’s switch back to the original topic: Although the carousel-like behavior of the ComboBox when used with touch interaction might be reasonable and more intuitive to use in most settings, there will be situations where you just wish to override that default behavior:

As mentioned before, the ComboBox uses the CarouselPanel as its default items panel template. The simplest solution is therefore to override the ComboBox’ ItemsPanelTemplate attribute and force it to use, for example, a StackPanel:

<ComboBox>
	<!-- insert other attributes here... -->
	<ItemsControl.ItemsPanel>
		<ItemsPanelTemplate>
			<StackPanel Orientation="Vertical" />
		</ItemsPanelTemplate>
	</ItemsControl.ItemsPanel>
<ComboBox> 

An even short (although less declarative) solution is to override the default items panel template without specifying any peculiar template panel:

<ComboBox>
	<!-- insert other attributes here... -->
	<ItemsControl.ItemsPanel>
<ItemsPanelTemplate />