You’re writing a WP8.1 XAML app and you’re looking for some kind of jumplist control. Well, you won’t find one and the LongListSelector is nonexistent unless you go back to using Silverlight. So read on if you want to create a proper jumplist experience with the proper Windows Phone UX.

Update: The contents of this post have been updated in Part 2 called “Making WP8.1 JumpLists Better” and most if not all of the resources have changed. This post will not be updated for historical purposes but the Sample Solution and Resources will reflect the most up to date implementation of the JumpList.

IMPORTANT: While these posts about JumpLists are super informative, I highly recommend checking out my JumpList controls in my QKit library and download them from nuget. QKit includes ready-to-use controls like the AlphaJumpList control so you don’t have to deal with the headaches of implementing it from scratch along with several other useful controls. You can also view the source code on http://qkit.codeplex.com/.

The Material

The Problem

Windows Phone has a unique way to group and traverse through a list very quickly. In Silverlight apps, we were given a dedicated control called the LongListSelector that enabled third party apps to simulate that experience. With the new Universal app model and WP8.1 XAML running on WinRT, that control is not available. That’s the first problem. The second problem is even if we can create the jumplist experience, it might not to look and feel like the native jumplists that are in the people hub and the app list since there are no XAML resources, styles, or samples for this. This means that developers will have to come up with their own solution. Some will have pixel-perfect recreations of the jumplist while others will be happy with a “close enough” solution.

The Solution

First, let’s prepare our data. The data needs to be grouped properly and I’ve written a “JumpListHelper” helper class that you can drop in and reuse for all of your jumplist needs. It groups and sorts the list into a list of JumpListGroup objects using two extension methods. To group the items into alphabetical groups like you’d find in the app list, you simple add a using statement to my helper class and then call:

var groups = items.ToAlphaGroups(x => x.Name);

…where “items” is a list of objects you want to display in your list. The ToAlphaGroups method takes a function that gets the value of the object you want to group and sort on. In this case, my items have a property called “Name” and using a lambda function, I’m selecting that property. Use this extension method if you want the following experience:

To group it into a more generic group, my helper class also has a ToGroups method.

var groups = items.ToGroups(x => x.Name, x => x.Category);

This method takes two functions as parameters to define its sort and grouping values separately. In this case, I still want the items to be sorted by name, but I want the items to be grouped by the “Category” property. This is generally used to get a more general grouping of lists and this kind of jumplist can be found in the photos app.

Once the data is grouped, we will be using a CollectionViewSource class to expose it to the jumplist via binding. Just create a property in your viewmodel and instantiate it like this:

private CollectionViewSource collection; public CollectionViewSource Collection { get { if (collection == null) { collection = new CollectionViewSource(); collection.Source = groups; //groups is the result of using my extension methods above collection.IsSourceGrouped = true; } return collection; } }

Now, we’ll actually build the UI for the jumplist. The jumplist is created using a combination of 3 controls:

ListView – the ListView is the go-to list control in WinRT to display your items. It’s virtualized, enables animations, and maintains the current view.

– the ListView is the go-to list control in WinRT to display your items. It’s virtualized, enables animations, and maintains the current view. GridView or 2nd ListView – a GridView will be used when displaying all of the letters your list can jump to (for alpha-jumplists) while another ListView is used to display all categories/groups (generic jumplists).

– a GridView will be used when displaying all of the letters your list can jump to (for alpha-jumplists) while another ListView is used to display all categories/groups (generic jumplists). SemanticZoom – this controls acts as switch between the two previous controls. When in the normal ListView control, tapping on the letter or group header will automatically bring up the second ListView/GridView.

To set up the jumplist, we combine the controls like so:

<SemanticZoom Style="{StaticResource AlphaJumpListStyle}"> <SemanticZoom.ZoomedInView> <ListView ItemsSource="{Binding Collection.View}"> <ListView.GroupStyle> <GroupStyle HeaderTemplate="{StaticResource AlphaGroupHeaderTemplate}" HeaderContainerStyle="{StaticResource JumpListListHeaderContainerStyle}" HidesIfEmpty="True" /> </ListView.GroupStyle> <ListView.ItemTemplate> <DataTemplate> ... </DataTemplate> </ListView.ItemTemplate> </ListView> </SemanticZoom.ZoomedInView> <SemanticZoom.ZoomedOutView> <GridView ItemsSource="{Binding Collection.View.CollectionGroups}" ItemTemplate="{StaticResource AlphaJumpListItemTemplate}" /> </SemanticZoom.ZoomedOutView> </SemanticZoom>

Note: All of the styles and templates will be available in the sample project at the beginning of this post.

Let’s break down what’s going on. The SemanticZoon control has a style applied to it and it is required for it to look like a proper jumplist. The style is also different between the alpha jumplist and the generic jumplist so be sure to apply the right one. The reason for this is because the alpha jumplist uses a Viewbox control to keep the UX consistent with the OS. The letters grid when the alpha jumplist is open is one of the few areas in the OS that doesn’t change between different screen resolutions and sizes. WP8 will scale elements on the screen differently for different screens. But with the letters grid, it’s stretched to fill the screen as if it’s an image. To accomplish this in our jumplists, we need to use the Viewbox control. You can see the difference it makes below (Viewbox used on the left) on a 1080p 5.5in device.

Note that only the alpha jumplist exhibits this behavior so it’s the only one to use the Viewbox in its style. The generic jumplist doesn’t use it.

Now digging deeper, we can see that the SemanticZoom control has a zoomed in and zoomed out component. The zoomed in view is the main ListView that the user will be first presented with. This zoomed in ListView’s ItemsSource is bound to the CollectionViewSource that we created. It also has a GroupStyle that defines how the headers will look. The GroupStyle defines a template for the header but also has a container style that fixes a bug where the first header will disappears when you navigate away from the page. Make sure to include this container style (thanks to Kinnara on the MSDN forums for solving this issue).

The zoomed out view is shown when the user taps on a group header. It is a GridView for an alpha jumplist and a ListView for a generic jumplist. Its ItemsSource is bound to the CollectionViewSource but to the View’s CollectionGroups collection. Make sure to check out the sample project to define the XAML properly and all of the styles and templates. Omitting anything runs the risk of the jumplist not working properly, reintroducing a bug, or making it look incorrect.

Remarks

This currently doesn’t work in landscape. Because alpha jumplist’s GridView doesn’t scale against the screen resolution, a Viewbox control was used in the SemanticZoom zoomed out view. Unfortunately, using a Viewbox means that I had to hard code the size and currently doesn’t resize when the phone rotates. So don’t enable landscape orientation for pages that use alpha jumplists. The generic jumplist works fine with page rotation, however.

There is also a performance issue when there’s a CommandBar on the page. The SemanticZoom control automatically hides the CommandBar when the user taps on the group header but it’s somewhat slow on a real device. I suggest hooking up to the SemanticZoom.ViewChangeStarted event and hiding the CommandBar manually like so:

private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e) { if (e.IsSourceZoomedInView) this.BottomAppBar.Visibility = Visibility.Collapsed; else this.BottomAppBar.Visibility = Visibility.Visible; }

Finally, these styles do not currently support the high contrast mode that Windows Phone can be in. In some cases, text is unreadable in high contrast mode and at the very least, it doesn’t match the system UI in high contrast mode. I’ll probably be revisiting this at a later time to get the high contrast mode working properly but right now it’s not a priority.