This blog post describes a Windows Phone 7 NavigationList control, a list control designed for navigation pages. The NavigationList renders twice as fast as a ListBox and has a slightly simpler API.
A few months ago I blogged about the relative performance of the Windows Phone 7 emulator versus the same code being run on the real hardware. There were a couple of take-home messages from this blog post, firstly the performance on real hardware is typically much slower than the emulator, and secondly an ItemsControl can render the same content as a ListBox in less time, making them a better choice for rendering lists of items for navigation.
The recent NoDo updates included some performance improvements, most of which focus on load performance. I re-ran the tests from my previous blog post pre-NoDo and after installing NoDo on the phone (Samsung Omnia), but saw no difference in performance between my measurements, which is pretty much what I expected:

Load time is still a significant issue for Windows Phone 7 Silverlight applications, and anything that can be done to reduce this will make your application more slick and useable.
I still see examples on the internet of people using the ListBox for navigation within Windows Phone 7 application, despite the poor performance when compared with an ItemsControl. This is probably because ListBox has a slightly simpler API. In order to combat this I have come up with a NavigationList control, which is based on an ItemsControl. This control wraps up all the ItemsControl configuration and click / manipulation handling to give a fast and easy-to-use control which simply raises a Navigation event in response to user interactions.
NavigationList Control
The NavigationList control is a lightweight control that can be used to render a list of items (base on an ItemTemplate). The following XAML snippet shows how to use this control:
<l:NavigationList ItemsSource="{Binding}" Navigation="NavigationList_Navigation"> <l:NavigationList.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" FontSize="25"/> </DataTemplate> </l:NavigationList.ItemTemplate> </l:NavigationList> |
The NavigationList has an ItemsSource property which is used to supply your list of items, and an optional ItemTemplate template where you specify how they are rendered.
The control fires a Navigation event whenever the user clicks on an item. This event has an Item argument which contains the item (from the ItemsSource) that was selected. This is typically used to navigate to a new page, as in the example below:
private void NavigationList_Navigation(object sender, NavigationEventArgs e) { // pass the datacontext to the page we are navigating to via the RootVisual. FrameworkElement root = Application.Current.RootVisual as FrameworkElement; root.DataContext = e.Item; NavigationService.Navigate(new Uri("/DetailsPage.xaml", UriKind.RelativeOrAbsolute)); } |
So, how does the NavigationList compare to a ListBox? In terms or performance, it is a clear winner. The example project for this blog post has a test which renders exactly the same content with a ListBox and a NavigationList. Here’s how the load time of the page compares:

A page which uses a NavigationList renders twice as fast as an equivalent page that uses a ListBox!
Another problem with using ListBox is that selection state is ‘persisted’ in the back stack, therefore when you navigate back to the page, you must clear the SelectedItem. Interestingly I just spotted a blog post by a WP7 developer who’s application was rejected during the marketplace submission process for forgetting to do just this!
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { base.OnNavigatedTo(e); // reset selection so that the same item can be re-selected navigationListBox.SelectedItem = null; } private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (navigationListBox.SelectedItem == null) return; // pass the datacontext to the page we are navigating to via the RootVisual. FrameworkElement root = Application.Current.RootVisual as FrameworkElement; root.DataContext = navigationListBox.SelectedItem; NavigationService.Navigate(new Uri("/DetailsPage.xaml", UriKind.RelativeOrAbsolute)); } |
NavigationList Implementation
The control itself is quite simple, the template includes an ItemsControl, which binds to the NavigationList ItemsSource and ItemTemplate dependency properties. The ItemsControl uses a VirtualizingStackPanel for the ItemsPanel to give a faster load time (as does the
ListBox):
<Style TargetType="l:NavigationList"> <Setter Property="ItemTemplate"> <Setter.Value> <DataTemplate> <TextBlock Text="{Binding}"/> </DataTemplate> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate> <l:ItemsControlEx x:Name="itemsControl" ItemsSource="{Binding Path=ItemsSource, RelativeSource={RelativeSource TemplatedParent}}" ItemTemplate="{Binding Path=ItemTemplate, RelativeSource={RelativeSource TemplatedParent}}"> <l:ItemsControlEx.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel Orientation="Vertical"/> </ItemsPanelTemplate> </l:ItemsControlEx.ItemsPanel> <l:ItemsControlEx.Template> <ControlTemplate> <ScrollViewer> <ItemsPresenter/> </ScrollViewer> </ControlTemplate> </l:ItemsControlEx.Template> </l:ItemsControlEx> </ControlTemplate> </Setter.Value> </Setter> </Style> |
ItemsControlEx is a simple subclass of ItemsControl which raises an event each time an item is added to the panel:
/// <summary> /// Extends an ItemsControl, raising an event when the PrepareContainerForItemOverride /// override is invoked. /// </summary> public class ItemsControlEx : ItemsControl { protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { base.PrepareContainerForItemOverride(element, item); OnPrepareContainerForItem(new PrepareContainerForItemEventArgs(element, item)); } /// <summary> /// Occurs when the PrepareContainerForItemOverride method is invoked /// </summary> public event EventHandler<PrepareContainerForItemEventArgs> PrepareContainerForItem; /// <summary> /// Raises the PrepareContainerForItem event. /// </summary> protected void OnPrepareContainerForItem(PrepareContainerForItemEventArgs args) { if (PrepareContainerForItem != null) { PrepareContainerForItem(this, args); } } } /// <summary> /// Provides data for the PrepareContainerForItem event. /// </summary> public class PrepareContainerForItemEventArgs : EventArgs { public PrepareContainerForItemEventArgs(DependencyObject element, object item) { Element = element; Item = item; } public DependencyObject Element { get; private set; } public object Item { get; private set; } } |
The NavigationControl locates the ItemsControlEx instance from its template to handle this event. Each time an element is added, handlers are added to various events:
public override void OnApplyTemplate() { base.OnApplyTemplate(); var itemsControl = GetTemplateChild("itemsControl") as ItemsControlEx; itemsControl.PrepareContainerForItem += ItemsControl_PrepareContainerForItem; } private void ItemsControl_PrepareContainerForItem(object sender, PrepareContainerForItemEventArgs e) { var element = e.Element as UIElement; // handle events on the elements added to the ItemsControl element.MouseLeftButtonUp += Element_MouseLeftButtonUp; element.ManipulationStarted += Element_ManipulationStarted; element.ManipulationDelta += Element_ManipulationDelta; } |
The above could have been achieved without the use of ItemsControlEx by providing a container for each item that is added, much the same was as the ListBox contains items within a ListBoxItem instance. However, the aim here is to make the control as lightweight as possible, which means minimizing the number of visual elements created.
The Element_MouseLeftButtonUp event handler raises the Navigation event, but what are the manipulation event handlers for? This is because if the NavigationList is used within a control that performs some action due to manipulation, the Pivot control which reacts to swipe for example, a mouse up event is still fired when the manipulation ends. This results in a navigation firing incorrectly, see Tore Lervik’s blog for more details.
private bool _manipulationDeltaStarted; private void Element_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) { _manipulationDeltaStarted = true; } private void Element_ManipulationStarted(object sender, ManipulationStartedEventArgs e) { _manipulationDeltaStarted = false; } private void Element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (_manipulationDeltaStarted) return; // raises the Navigation event on mouse up, but only if a manipulation delta // has not started. var element = sender as FrameworkElement; OnNavigation(new NavigationEventArgs(element.DataContext)); } |
So there you have it, the NavigationList, simple and fast.
Now people … please stop using ListBox for navigation, it is slow and it’s API is cumbersome!
You can download the sourcecode here:NavigationListControl.zip
Regards, Colin E.
Tags: codeproject, NavigationList, WP7


email: ceberhardt@scottlogic.co.uk
on Google+



The reason why it is faster is the fact that the items are not ListBoxItems but ContentPresenter. So there is less to render because a ListBoxItem has a rich template with VisualStates. Each element in the template takes time to render.
If you compare the time using an ItemsPresenter directly and include a ScrollViewer in the ControlTemplate and use a VirtualizingStackPanel, then it is even faster than NavigationListControl. If you replace the ListBoxItemTemplate with a TextBlock using ListBox.ItemContainerStyle, then it is also significantly faster. I would also recommend to use ItemContainerStyle instead of ItemTemplate for ListBoxes because it simplifies the layout.
Great control but I found when used in conjunction with your excellent tilt behaviour that for some reason, the control gets into a state where mousedown doesn’t fire and no selection is ever picked up. Anyone else seen this?
Hi,
Have you tried this out in Mango? I am considering implementing this approach in my app, but wondered if ListBoxes were still as slow?
Thanks
Chris
Hi Colin
Thank you for this post. I don’t get what you mean by ‘using ListBox for navigation’. If I’m using the ListBox to display a list of the possible UIs to which the user can navigate, this list will mostly be short. Most apps have only 3-20 different UI screens, so I don’t see why this should be a performance problem.
But if you’re talking about ListBoxes which display hundreds or thousands of entries (phone numbers, apps on the market etc.), why do you talk about ‘ListBox for navigation’?
Thanks
Jeff
Hey,
Running into an issue with the NavigationList. If I use a more complex ItemTemplate, that binds say two text fields, When scrolling through the list very fast, I get BindingExpression errors.
I can send you a reproduceable code sample.
Hi Jeff,
A repro of this issue would be great thanks
Thanks for the article!
I wonder if it is possible to implement WarpPanel into navigationlist-control?
Sure – just change the template!
Suppose I add 20 items to list and display it using NavigationList and on clicking on a single item I navigate to the item page I add one more to the same list now I navigate back to the page where list is displayed using NavigationList. It is not updated i.e. its still showing 20 items where as it should show 21 items. I tried to update layout but nothing happened.
Hi Colin,
I’m creating a NavigationList in the code behind because I’m dynamically adding PivotItems:
var root = (FrameworkElement)Application.Current.RootVisual;
var workout = (Workout)root.DataContext;
var p = new PivotItem {Header = workout.RoutineOne.Name.ToLower()};
var navList = new NavigationList
{
ItemTemplate = CreateDataTemplate(),
ItemsSource = workout.RoutineOne.ExerciseRef
};
p.Content = navList;
WorkoutPivot.Items.Add(p);
When I try to set the Navigation in the item initializer, i.e.
Navigation = lstWorkout_Navigation
I get a design time error – Field or property expected.
Is it possible to set the Navigation event handler in code behind?
Thanks,
Jeff
Nevermind, figured it out. Outside the initializer,
navList.Navigation += lstWorkout_Navigation;
Thanks,
Jeff
I’ve tried using this in combination with the LowProfileImageLoader (http://blogs.msdn.com/b/delay/archive/2010/09/02/keep-a-low-profile-lowprofileimageloader-helps-the-windows-phone-7-ui-thread-stay-responsive-by-loading-images-in-the-background.aspx), but it’s giving me a NullReferenceException when I start scrolling through the list.
System.NullReferenceException was unhandled
Message=NullReferenceException
StackTrace:at WP7Contrib.View.Controls.LowProfileImageLoader.WorkerThreadPro(Object unused)
at System.Threading.ThreadHelper.ThreadStartHelper(ThreadHelper t)
at System.Threading.ThreadHelper.ThreadStartHelper()
I’d expect it something to do with the list holding back items until you scroll down to them?
That’s odd – I’ll see if I can test that out at some point today. he two of them should play nicely together!
You will have a null Uri reference. I fixed this by putting a null check on this line:
if (pendingRequest.Uri != null && pendingRequest.Uri.IsAbsoluteUri)
Thanks for this detailed technical analysis.Besides I agree with ‘Horst’.This approach can be used to enhance performance in WPF too.
Thanks for the article!
Do you think a similar approach could help improve performance in WPF?
Thanks Horst,
Good idea, this approach may help WPF performance. However, for WP7 the main problem here is that people are using a ListBox for something which it is not really designed for. It just happens to be the only framework control that can easily be used to create a ‘navigation list’. As a result, performance suffers because of the ListBox features that are not being used (i.e. selection which is immediately reset when it changes).
Within WPF ListBoxes are typically used for their intended purpose – i.e. providing a means to select items within a list!
Regards, Colin E.
[...] A Fast Loading Windows Phone 7 NavigationList Control (Colin Eberhardt) [...]
A Fast Loading Windows Phone 7 NavigationList Control | Colin Eberhardt’s Adventures in WPF…
Thank you for submitting this cool story – Trackback from DotNetShoutout…