A Windows Phone 7 Jump List Control

January 20th, 2011 by Colin Eberhardt

This blog post presents a Windows Phone 7 Jump List control that I have developed.This post describes the API in detail and includes full sourcecode. Feel free to use and enjoy!

The video below shows the control working on the emulator, the video further down this page shows it working on a real device. Full sourcecode is linked at the end of this article.

Introduction

For Silverlight developers Windows Phone 7 is a dream come true, a mobile platform that supports a language / framework they already know, or as Jesse Liberty puts it, “You are already a Windows Phone Developer“. What I find really cool about Silverlight for WP7 is that exactly the same controls can be used both on the web and the mobile. However, the controls for Windows Phone 7 are tailored specifically for the mobile form factor having larger areas to ‘hit’, and gestures for scrolling for example. Despite this, there are times when you really need a control that is specific to the mobile platform.

Navigating long lists of data is a chore on a mobile device. On the desktop / web you can click on the scrollbar and navigate the full length of the list with a single gesture, whereas navigating the same list on a mobile requires multiple swipe gestures. This is where a Jump List comes in handy!

A Jump List groups the items within the long list into categories. Clicking on a category heading (or jump button) opens up a category view, where you can then click on one of the other categories immediately causing the list to scroll to the start of this newly selected category.

This blog post describes the API of the Jump List control I have developed. A link to the full sourcecode and a demo application can be found at the end of this blog post.

The video below shows the JumpList working (and performing well!) on a Samsung Omnia WP7. Apologies for the poor video quality!

Basic Example

The API for the JumpList is quite similar to that of the ListBox, it has an ItemsSource property which you set (or bind) the collection of objects you wish to render in the list. The appearance of each item is specified by an ItemTemplate. The example below shows a JumpList bound to a collection of simple Person objects:

public class Person
{
  public string Surname { get; set; }
  public string Forename { get; set; }
}
 
// ItemsSource set in constructor of control ....
list.ItemsSource = PersonDataSource.CreateList(50);

(As an aside, the PersonDataSource above generates pseudo-random names using Markov Chains using some code I found online)

<l:JumpList x:Name="list"
            ScrollDuration="400">
 
  <!-- category provider - details how the items are grouped -->
  <l:JumpList.CategoryProvider>
    <l:AlphabetCategoryProvider PropertyName="Surname"/>
  </l:JumpList.CategoryProvider>
 
  <!-- item template - details how each item is rendered in the list -->
  <l:JumpList.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal"
                  Margin="0,3,0,3"
                  Height="40">
        <Image Source="Head.png"
                Opacity="0.7"
                Width="40" Height="40"/>
        <TextBlock Text="{Binding Surname}"
                    Margin="3,0,0,0"/>
        <TextBlock Text=", "/>
        <TextBlock Text="{Binding Forename}"/>
      </StackPanel>
    </DataTemplate>
  </l:JumpList.ItemTemplate>
 
</l:JumpList>

The main difference between the JumpList and a ListBox is that a JumpList requires that you supply a CategoryProvider. In the example above an AlphabetCategoryProvider was supplied which groups the supplied objects (in this case Person instances) based on the first letter of the property indicated by the PropertyName of the AlphabetCategoryProvider. In this example, the items are being grouped by the Surname property.

The animated scrolling as the list jumps from one category to the next can be controlled via the ScrollDuration property. The animated ‘reveal’ effect as the category buttons are drawn can be controlled via the CategoryTileAnimationDelay property which details the time between the animation being started for neighbouring category buttons.

Note, for very long lists with hundreds of items it makes sense to disable the scrolling effect as the list ‘jumps’ to the selected category.

The jump buttons that appear at the top of each group can be configured via properties that specify their style, template and item template. You can consult the API for more details. The category buttons which are rendered in the category view also have three similar properties. For example, you can use the JumpButtonStyle to make each button the same size, or the CategoryButtonStyle to create larger category buttons.

Selection

The JumpList exposes a SelectedItem property which can be used to get or set the currently selected item. This property also permits TwoWay binding to other controls or a View Model. The JumpList also exposes a SelectionChanged event which is fired whenever the SelectedItem property changed, this event is useful for more programmatic / non-databound usages.

The following code snippet shows a simple UI binding of the JumpList SelectedItem:

<StackPanel DataContext="{Binding Path=SelectedItem, ElementName=list}">
  <TextBlock Text="SELECTED ITEM:"/>
  <!-- displays the Name property of the object bound to the JumpList -->
  <TextBlock Text="{Binding Name}"/>
</StackPanel>
 
<l:JumpList x:Name="list">
  <!-- ItemTemplate etc ... -->
</l:JumpList>

Each item within the JumpList is contained within a JumpListItem. When an item is selected, the default JumpList item template changes the Foreground colour to PhoneAccentBrush. It is possible to style and template the JumpListItems via the JumpListItemStyle property. The following example adds a Border element and sets the Background colour of this Border when an item is selected:

<l:JumpList.JumpListItemStyle>
  <Style TargetType="l:JumpListItem">
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Background" Value="#222"/>
    <Setter Property="Padding" Value="2"/>
    <Setter Property="Margin" Value="0"/>
    <Setter Property="HorizontalContentAlignment" Value="Right"/>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="l:JumpListItem">
          <Border x:Name="LayoutRoot"
                  Background="{TemplateBinding Background}"
                  HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                  VerticalAlignment="{TemplateBinding VerticalAlignment}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}">
            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Normal"/>
                <VisualState x:Name="MouseOver" />
                <VisualState x:Name="Disabled"/>
              </VisualStateGroup>
              <VisualStateGroup x:Name="SelectionStates">
                <VisualState x:Name="Unselected"/>
                <VisualState x:Name="Selected">
                  <Storyboard>
                    <!-- change the background on selection -->
                    <ColorAnimation
                        Storyboard.TargetName="LayoutRoot"
                        Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                        To="#555"
                        Duration="0:0:0.5">
                    </ColorAnimation>
                  </Storyboard>
                </VisualState>
              </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
 
            <ContentControl x:Name="ContentContainer"
                      VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                      HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                      Margin="{TemplateBinding Padding}"
                      Content="{TemplateBinding Content}"
                      ContentTemplate="{TemplateBinding ContentTemplate}"
                      Foreground="{TemplateBinding Foreground}" />
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</l:JumpList.JumpListItemStyle>

The Category Provider

As seen in the earlier example, the JumpList uses a category provider, specified via the JumpList.CategoryProvider property to place items into categories within the jump list. The CategoryProvider implements the following interface:

/// <summary>
/// A category provider assigns items to categories and details
/// the full category list for a set of items.
/// </summary>
public interface ICategoryProvider
{
  /// <summary>
  /// Gets the category for the given items
  /// </summary>
  object GetCategoryForItem(object item);
 
  /// <summary>
  /// Gets the full list of categories for the given items.
  /// </summary>
  List<object> GetCategoryList(IEnumerable items);
}

The GetCategoryForItem method is used to determine the category for each item in the list, whilst GetCategoryList returns the full list of categories in order to display the category view.

The JumpList comes with a couple of ‘built in’ category providers:

The AlphabetCategoryProvider uses the first letter of a named property to identify the category for each item. The category list which AlphabetCategoryProvider provides is always the full alphabet. The category view ‘grays’ category buttons for which the source list has no items.

The DistinctPropertyValueCategoryProvider is a slightly more generic provider, placing items into categories based on the value of the property nominated via PropertyName. With this provider the category list displays all the unique or distinct values found for the given property.

For example, if you have a list of events which you want to group by month, you can use a DistinctPropertyValueCategoryProvider identifying a property on your object which indicates the month. For example:

public class JugglingEvent
{
  public string Name { get; set; }
  public DateTime Date { get; set; }
  public string Description { get; set; }
 
  public int Month
  {
    get
    {
      return Date.Month;
    }
  }
}

The category provider is detailed as follows:

<!-- category provider groups by month-->
<l:JumpList.CategoryProvider>
  <l:DistinctPropertyValueCategoryProvider
        PropertyName="Month"/>
</l:JumpList.CategoryProvider>

This will group the items by month. However, the Month property exposes an integer, and this will be supplied as the DataContext for the jump buttons and category buttons. In order to display the month indices as their respective strings, a value converter can be supplied to the jump button and category button item templates:

<!-- the jump button template renders the month as a string -->
<l:JumpList.JumpButtonItemTemplate>
  <DataTemplate>
    <TextBlock Text="{Binding Path=., Converter={StaticResource MonthIndexToStringConverter}}"/>
  </DataTemplate>
</l:JumpList.JumpButtonItemTemplate>
 
<!-- the category template renders the month as a string -->
<l:JumpList.CategoryButtonItemTemplate>
  <DataTemplate>
    <TextBlock Text="{Binding Path=., Converter={StaticResource MonthIndexToStringConverter}}"/>
  </DataTemplate>
</l:JumpList.CategoryButtonItemTemplate>

Custom Category Button Animations

When the category view is displayed, each category button is revealed via a storyboard. These storyboards are started sequentially with a delay, specified by the CategoryTileAnimationDelay property, between the start of neighbouring buttons.

The storyboards that define the animation are within the template of the category buttons. The JumpList control looks for two storyboards, name “ShowAnim” and “HideAnim”, and triggers these to show / hide the button respectively.

If you want to disable animations altogether, you can omit these storyboards. You can also specify your a custom animation by inserting your own storyboards into the category button template.

The example below adds a custom animation which reveals each button by rotating it around its centre:

<!-- create a custom category button animation -->
<l:JumpList.CategoryButtonTemplate>
  <ControlTemplate TargetType="Button">
    <Grid Background="Transparent"
        x:Name="Parent"
        RenderTransformOrigin="0.5,0.5">
      <Grid.Resources>
        <Storyboard x:Key="ShowAnim">
          <DoubleAnimation To="0" Duration="0:0:0.3"
                            Storyboard.TargetName="Parent"
                            Storyboard.TargetProperty="(Grid.Projection).(PlaneProjection.RotationX)"/>
        </Storyboard>
        <Storyboard x:Key="HideAnim">
          <DoubleAnimation To="90" Duration="0:0:0.1"
                            Storyboard.TargetName="Parent"
                            Storyboard.TargetProperty="(Grid.Projection).(PlaneProjection.RotationX)"/>
        </Storyboard>
      </Grid.Resources>
      <Grid.Projection>
        <PlaneProjection RotationX="90"/>
      </Grid.Projection>
 
      <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
          <VisualState x:Name="Normal"/>
          <VisualState x:Name="MouseOver"/>
          <VisualState x:Name="Pressed">
            <Storyboard>
              <ColorAnimation To="White" Duration="0:0:0"
                            Storyboard.TargetName="Background"
                            Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)"/>
            </Storyboard>
          </VisualState>
          <VisualState x:Name="Disabled">
            <Storyboard>
              <DoubleAnimation To="1" Duration="0:0:0"
                            Storyboard.TargetName="DisabledBackground"
                            Storyboard.TargetProperty="(Rectangle.Opacity)"/>
              <DoubleAnimation To="0" Duration="0:0:0"
                            Storyboard.TargetName="Background"
                            Storyboard.TargetProperty="(Rectangle.Opacity)"/>
            </Storyboard>
          </VisualState>
        </VisualStateGroup>
      </VisualStateManager.VisualStateGroups>
      <Rectangle  x:Name="Background"
                      Fill="{StaticResource PhoneAccentBrush}"/>
      <Rectangle  x:Name="DisabledBackground"
                      Fill="{StaticResource PhoneBackgroundBrush}"
                      Opacity="0"/>
      <ContentControl x:Name="ContentContainer"
                    Foreground="{TemplateBinding Foreground}"
                    HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                    VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                    Padding="{TemplateBinding Padding}"
                    Content="{TemplateBinding Content}"
                    ContentTemplate="{TemplateBinding ContentTemplate}"/>
    </Grid>
  </ControlTemplate>
</l:JumpList.CategoryButtonTemplate>

If you have many categories, and want to disable the ‘reveal’ animation, simply supply a template without any storyboards, see the demo sourcecode for an example.

You can download the full sourcecode: WP7JumpList.zip

To run this code you will also need the Windows Phone 7 Toolkit.

If you have any feedback, ideas or bugs to report – please let me know!

Regards, Colin E.

Tags:

75 Responses to “A Windows Phone 7 Jump List Control”

  1. Artur says:

    Hello Colin,
    Thank you very much not only for this great control, but also for your whole Blog, I am reading each of your articles as you publish them with great pleasure, and there is always something to learn – even when I thought to master the topic:-)

    Related to the porting of this Control to WP7.1, the control is unfortunately broken in the WP7Contrib NuGet package too, it would be great if you can arrange a fix.

    For your readers who need it earlier, here is the FIX (al least that’s what worked out for me):
    It seems that the reason for the “Unspecified Error” mentioned in the last comments is due to the missing TargetType in three sections in the file “generic.xaml”.

    To fix this, find the string “” in the mentioned file and replace it as follows (the leading lines are shown only to help you identifying the context):

    <ControlTemplate>

    Line 58:
    <ControlTemplate TargetType=”Button”>

    Line 223:
    <ControlTemplate TargetType=”l:JumpList”>

    Line 272:
    <ControlTemplate TargetType=”ItemsControl”>

    • Hi Artur,

      Thank you :-) … I promise I will fix this shortly – I have just been mega-busy!

      Colin E.

    • Jostien Sand says:

      Hi,

      how do you port it to WP7.1 ? I have changed the suggested controlTemplates in generic.xaml and then changed the project to 7.1. Now when I build the project I get an error saying: “A namespace cannot not directly contain members such as fields or methods.”

      What am I doing wrong? Any help is very appreciated :)

  2. Al says:

    Hi there,
    I posted a couple of days ago but it didn’t seem to take.
    I’m trying, so far unsuccessfully, to use this control. I can run your sample code, no problem, but when I try to put a JumpList into a new, empty project I’m hitting difficulties. The xaml appears to be OK, but as soon as I assign anything to the ItemsSource I’m getting ‘Unspecified error’. This is when using the 7.1 build from WP7Contrib.
    Is this build known to work?
    Thanks

    • Al says:

      On closer reading my issue is identical to the one described below by talluri.
      Note that putting the JumpList.ItemsSource = ….. within a try..catch block doesn’t catch the error. It still falls through to Application_UnhandledException.
      I’m unable to get the source working in a project which targets 7.1.
      Shame – it looks like a reat control, but I can’t use it. Interest to hear if anyone has got around this.

    • linh says:

      Hello, I just want to know the effect to make an image or a button jumping like that. Thank you so much.

  3. Alec says:

    Has anyone got this working on 7.1 yet? Using the binaries downloaded from WP7Contrib so far has just changed the compilation errors.

  4. talluri says:

    nice work. i am trying to use this control.. but getting unspecified error..
    I have created new project and added jumplistcontrol project to that. And added mainpage, demopageone,persondatasource and MarkovNameGenerator.cs. Am i missing any thing. I am using 7.1 version. I have already installed windows phone toolkit

    • The jump list control has been added to the WP7Contrib library which has a WP7.1 build.

    • dloendorf says:

      I am using the WP7Contrib version of the JumpList control and having the same issue. I create an ObservableCollection and set the list.ItemsSource to that collection. The StackPanel holding the list is collapsed when I do this. When I make the StackPanel visible I always receive an “unspecifed error” that is caught by the Application_UnhandledException event. I know there is data in each item of the collection and have checked to make sure the Binding values are indeed in the collection of values. The AlphabetCategoryProvider has been set to a Key (included in each item of the collection) that is the alpanumeric letter for the category.

      I am able to run the example project. I replaced the JumpListControl with the one from the WP7Contrib package and removed the old control from the project to insure I was using the WP7 version. My use of the control is very similar to the demopageone example only I am using an observablecollection instead of a list.

      Not sure how to debug this…any advice would be appreciated.

      David

      • OK – quite a few people are having issues – I’ll try to post an update shortly. Just a bit busy right now!

        • Jac says:

          Curious if there was an update to this? I’ve just upgraded my project to Mango and after replacing the original JumpListControl reference with the new wp7contrib library, I’m still seeing this Unspecified Error. I couldn’t find a new blog post or any references to this on the codeplex site, and I also couldn’t see a relevant-looking checkin since the bug description given below on September 12th with a suggested fix.

          Nice control, hope I haven’t just missed something obvious :)

  5. Gautam says:

    Hi,
    Thanks for this awesome control.
    I downloaded the source code and it worked perfectly.
    But I couldn’t use it in my project as my project targets Windows Phone 7.1
    Jump list control works perfect with Windows Phone 7.0.
    Can you provide me the control which is upgraded 7.1?

    Thanks
    Gautam

  6. Ian says:

    Great control. Thanks for the efforts

  7. Agile Hobo says:

    Another scenario: While _categoryItemsControl is showing, navigate to another page. When you navigate back, _jumpListControl is disabled

  8. Agile Hobo says:

    The problem also happens with custom category animation. When the category list is showing, if you click one of the buttons to change animation style, category list is disappear and jump list is disabled.

  9. Agile Hobo says:

    I found a bug when updating the bound list. When the _categoryItemsControl is shown, if you change ItemSource of the list, _categoryItemsControl will dissappear and the _jumpListControl is disabled.

    Please fix it. Thanks.

  10. TheBeO says:

    Hi,

    first of all, thanks for your great control. It works fine under a WP7.0 project. But I’ve tried to add it to a 7.1(RC) project, with the latest Toolkit (august release) … damn I’ve a “unspecified error”. I’ve tried to update your project to 7.1 (without and after with updating toolkit), this is the same: “unspecified error”, and stacktrace from inner exception is:
    at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
    at MS.Internal.XcpImports.UIElement_Measure_WithDesiredSize(UIElement element, Size availableSize)
    at System.Windows.UIElement.Measure_WithDesiredSize(Size availableSize)
    at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(UIElement child, Size layoutSlotSize)
    at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint)
    at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight)
    at MS.Internal.XcpImports.MeasureOverrideNative(IntPtr element, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)
    at MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement element, Size availableSize)
    at System.Windows.FrameworkElement.MeasureOverride(Size availableSize)
    at System.Windows.Controls.ScrollContentPresenter.MeasureOverride(Size constraint)
    at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight)
    at MS.Internal.XcpImports.MeasureNative(IntPtr element, Single inWidth, Single inHeight)
    at MS.Internal.XcpImports.UIElement_Measure(UIElement element, Size availableSize)
    at System.Windows.UIElement.Measure(Size availableSize)
    at System.Windows.Controls.ScrollViewer.MeasureOverride(Size constraint)
    at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight)
    at MS.Internal.XcpImports.MeasureOverrideNative(IntPtr element, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)
    at MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement element, Size availableSize)
    at System.Windows.FrameworkElement.MeasureOverride(Size availableSize)
    at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight)
    at MS.Internal.XcpImports.MeasureOverrideNative(IntPtr element, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)
    at MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement element, Size availableSize)
    at System.Windows.FrameworkElement.MeasureOverride(Size availableSize)
    at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight)
    at MS.Internal.XcpImports.MeasureOverrideNative(IntPtr element, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)
    at MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement element, Size availableSize)
    at System.Windows.FrameworkElement.MeasureOverride(Size availableSize)
    at Microsoft.Phone.Controls.PivotItem.MeasureOverride(Size availableSize)
    at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight)

    any ideas? Thanks

  11. Priya says:

    Hi Colin,
    This is a great control, thank you for sharing. Just wanted to let you know that I’ve used your code to create a slightly different version of the control – I needed a slightly different “flavor”! Here’s the link to the post and the code:
    http://priyarules.posterous.com/categorized-list-selector-for-windows-phone-7

    cheers,
    Priya

  12. Terry Pearson says:

    Colin,

    Great article, fabulous series. Very useful, thanks for the effort.

    I think that I have found a small issue with your Jumplist that came up when I was implementing tombstoning. When programatically setting the SelectedItem property, the property is set but the item in the list is not highlighted.

    To see this in action with some test code, add the following method to your DemoPageOne class:

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
    base.OnNavigatedTo(e);

    var selectedItem = (from i in list.ItemsSource as List select i)
    .OrderBy(i => i.Surname)
    .FirstOrDefault();
    list.SelectedItem = selectedItem;
    }

    Unless I am missing something, the alphabetically first item (usually with a surname of “Aker”) in the list should be highlighted, but is not. Attempting to select the “Aker” item by touch or a mouse click does not highlight it, until another item is selected first, changing the SelectedItem reference, then it highlights.

    It appears that the dependency property SelectedItem SetValue method does not call the OnSelectedItemPropertyChanged event unless the new SelectedItem is different from the old SelectedItem.

    Can you suggest a fix?
    Thanks.

  13. Theniaky says:

    Hi and thank you for you JumpList : very beautiful and useful !

    I contact you because I have a problem with your module and the latest Mango Beta (Beta 2 Refresh) :

    1 – I select an item from a jumplist to push a new page (NavigationService.Navigate)
    2 – I go back to my jumplist
    3 – My list content disappears…

    First I thought it was because of my list size, but I just tried with a small list of 50 items et the problem is still there.

    I know Mango is still in beta, but as it looks like this build is nearly in RTM so I think the problem will be there in release.

    Thank you for you response.

  14. Danny says:

    Hey Scott great stuff, I have to ask though if you plan to update the jumplist to match how it works in Mango, where each category button is locked to the top of the listbox?

  15. John says:

    Great control!
    Have you tried it binding to a property as well as setting the ItemSource?

    John

  16. Alan Hoffman says:

    Hi Sir,

    Very nice control! Works like a dream in the emulator :) I am having serious perf issues on an actual phone though. I have a list about 200 long and the only thing contained in the items control datatemplate is a button with text content. It slows down to a standstill and makes it almost unusable. Is there any way for me to speed up performance?

    I am looking forward to the day when MS releases their control that displays the contact list in the people hub. SO SMOOOOOOOOTH

    • What aspect of the control slows down? This is certainly due to the underlying performance of Silverlight on WP7, however if you give me something specific i might be able to help.

  17. Mike F. says:

    Hey, just found this and its a breath of fresh air after fiddling with the longlistselector. But (of course there’s a but), it starts getting pokey to load with around 200 items, and I need it to be able to load 500 in a reasonable amount of time. Can you give me any general performance guidelines – what is it that determines load times, the complexity of the itemtemplate? Something else?

    Thanks, and great work!

    • Hi Mike,

      Glad you like it! I think expecting the list to load quickly with 500 items in a big ask. The phone hardware just isn’t that fast. The complexity of your ItemTemplate is critical, the visual tree construction and rendering is a big bottleneck on the phone.

      One trick I use to make the phone more responsive is a DeferredLoadContentControl:

      http://www.scottlogic.co.uk/blog/colin/2011/01/windows-phone-7-deferredloadcontentcontrol/

      This control will render a loading indicator before the required UI is actually rendered. This means that complex page layouts do not affect initial page load times making the phone feel much more responsive.

      Regards, Colin E.

  18. Amresh says:

    Hi,
    Thanks for creating such a nice control. I love this control as we have total control over everything from looks to animation.
    But, I’m stuck on one thing. If i select an item and go to another page such as details for the selected item, then after coming back i can’t select the same item again,as it is still selected.I tried making the SelectedItem=null, but that didn’t help me. Please throw some light on where i’m going wrong.
    Thanks.

    • Hi,

      Glad you like it! I can confirm that setting SelectedItem=null does work, I just double-checked. Are you sure that this code is actually being executed in your view? When you navigate to a view via the back-stack (i.e. back-button keypress) the view constructor is not invoked. You should add the logic into your override of the OnNavigatedTo method:

      protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
      {
      base.OnNavigatedTo(e);

      JumpListControl.SelectedItem = null;
      }

      Regards, Colin E.

      • Amresh says:

        Thanks, it works :-)

        • Amresh says:

          Hi,
          Again i’m stuck with the control.
          The problem is that whenever i press the last item displayed in the category view(when the resultant group is not visible), the app crashes with the follwing log…

          System.NullReferenceException occurred
          Message=NullReferenceException
          StackTrace:
          at System.Windows.DependencyPropertyChangedWeakListener.Disconnect()
          at System.Windows.DependencyPropertyChangedWeakListener.SourcePropertyChanged(DependencyObject c, DependencyProperty dp)
          at System.Windows.DependencyObject.OnPropertyChanged(DependencyProperty dp)
          at System.Windows.FrameworkElement.OnPropertyChanged(DependencyProperty dp)
          at System.Windows.DependencyObject.RaisePropertyChangeNotifications(DependencyProperty dp, Object newValue, Object oldValue)
          at System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value, Boolean allowReadOnlySet, Boolean isSetByStyle, Boolean isSetByBuiltInStyle, PropertyInvalidationReason reason)
          at System.Windows.DependencyObject.SetValueInternal(DependencyProperty dp, Object value, Boolean allowReadOnlySet)
          at System.Windows.Controls.ScrollViewer.set_ScrollableHeight(Double value)
          at System.Windows.Controls.ScrollViewer.InvalidateScrollInfo()
          at System.Windows.Controls.VirtualizingStackPanel.OnScrollChange()
          at System.Windows.Controls.VirtualizingStackPanel.SetAndVerifyScrollingData(Size viewport, Size extent, Vector offset)
          at System.Windows.Controls.VirtualizingStackPanel.UpdateLogicalScrollData(Size stackDesiredSize, Size constraint, Double logicalVisibleSpace, Size extent, Int32 lastViewport, Boolean isHorizontal)
          at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint)
          at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)
          at MS.Internal.XcpImports.MeasureOverrideNative(IntPtr element, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)
          at MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement element, Size availableSize)
          at System.Windows.FrameworkElement.MeasureOverride(Size availableSize)
          at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)

          I’m not getting why this is happening.Please help…

          • Amresh says:

            Got it figured.
            The jump list was getting out of the screen, beacuse of which it was crashing.
            Just decreased the height and solved the crash.

  19. Sean Bowker says:

    Hi Colin

    Excellent piece of work which I am using during my first steps with WP7 development.

    I do, however, have a bit of an issue with the category buttons. In your example above, you populate the buttons with a month name, and the button stretches across the screen. I have tried this, but the button remains the same small size (I see ‘Ja’ for January) positioned to the left of the screen.

    I have tried setting widths in the template but to no avail. How do I achieve what you show in your image?

    • Hi Sean,

      Glad you like it! Take a look at the example projects, example #5 selection. This sets the category button style to specify a fixed width the spans the width of the phone screen:

      [l:JumpList.CategoryButtonStyle]
      [Style TargetType="Button"]
      [Setter Property="Width" Value="420"/]
      [Setter Property="Margin" Value="10"/]
      [Setter Property="Padding" Value="8"/]
      [/Style]
      [/l:JumpList.CategoryButtonStyle]

      Regards, Colin E.

  20. Adrian Hara says:

    Fantastic work Colin, as usual :)

    I’ve noticed one problem on my device: oftentimes, while scrolling through the list an item will get selected, even though I don’t “tap” it. I’m guessing it’s because you subscribe to the LeftMouseButtonUp event and when it’s raised set the SelectedItem?…

  21. Thomas says:

    Hi Colin,

    Nice control !

    I have been looking for a control that displays a long list of items that is easy to search and accepts multiple item selection but so far nowhere to find.

    You think it is possible to make this jump list accept multiple item selection ?

    Or do I use a checkbox in my template ?

  22. Faz says:

    Ignore that last comment. This is a problem with the toolkit contextmenu control causing the behaviour I’m seeing.

  23. Faz says:

    Hi Colin

    great control. I’m pulling out LongListSelector as we speak!

    One small issue I’ve just found is that item selection is triggering on mouseup which has the effect of triggerring even while initiating a scroll. I haven’t looked into a fix yet but wanted to mention it in case this has already been resolved…

    regards

  24. [...] A Windows Phone 7 Jump List Control (Colin Eberhardt) [...]

  25. You may not want to call it a “Jump List” since there is already a control in the toolkit for this (LongListSelector)…but more importantly, a Windows 7 JumpList is very different this and I suspect others will be drawn here to think of something like the Windows 7 JumpList

    • Hi Shawn, some good points, I hadn’t thought about Windows 7 confusion, I quite often search for WP7 info on Google and accidentally end up on Windows 7 pages! However, there is already a precedent for calling this a jump list, with two other blogs mentioning this control by the same name here and here.

      I think LongListSelector is a terrible name! I hadn’t actually spotted that I was developing a control that was similar to one provided by the toolkit because of its non-descriptive name.

      I will stick to “Jump List” for now, but will look out for Win7 users ending up here by mistake. Thanke for your feedback.

  26. Stefan Volken says:

    Hi Colin
    Wow what a great control!
    I just had to download the code to test the control myself.
    Is it possible that the Jumplistcontrol project or dll is missing in the zip file?
    I would really like to test your great control?

    Thanks for checking!

    Regards from Switzerland!

  27. geogruven says:

    If items are added and removed dynamically from the source items collection will the groupings be handled automatically? For example, I have a long list of medical conditions and when the users selects one of those conditions, it should be removed from the long list as its already been selected. Say it was the only condition that began with the letter ‘x’, would that group label be disabled now?

    Thanks in advance, I look forward to using this control either way, the animation is a great plus.

    • Hi, Good point, I have just updated the code so that it should handle changes in the bound collection correctly. However, the list takes a little while to build, on my phone it is ~400ms, (the phone hardware is nowhere near as powerful as your desktop PCs!) so your idea of removing items might not be practical. How about adding a checkbox to your ItemTemplate and allowing users to multi-select?

  28. alan huffman says:

    Very nice work. Well done sir.

  29. [...] A Windows Phone 7 Jump List Control – Colin Eberhardt shares the implementation of a Jump List Control for the Windows Phone 7 platform, with a post which looks at the implementation and API offered by the control, videos of it in operation, and some examples along with the all important sourcecode so you can make use of the control. [...]

    • Zack says:

      Hi Colin, nice job! Just one issue though, when I run the app WP7JumpList (on emulator or on a device) go to the first list (#1 Small list – 50 items), and click any of the letter items, the app crashes with:

      XamlParseException occurred
      AG_E_PARSER_BAD_TYPE [Line: 1 Position: 173]

      It wouldn’t show me any source code in VS.

      Furthermore, I’m getting compilation warnings that “Microsoft.Phone.Controls.Toolkit” could not be found, and several others due to that fact. I did try referencing Microsoft.Phone in both projects, but the app still crashes after this. Might you have any ideas as to why this would be happening? Thanks!

      BTW, it seems to be happening in other lists too.

  30. Interesting work…
    I always wanted to be one of those jedi that can build a complex (and work-able) user control in wpf/sl.

    Btw, how this control compare with LongListSelector from the toolkit? I haven’t used the latter extensively, would you sum up the differences?

    • Don’t worry young Skywalker, you will be a Jedi one day!

      Regarding the LongListSelector, frustratingly I found out about that control when I was almost done with mine! I did take a very close look at the LongListSelector to see how it compared (to see whether it was worth publishing my control!)

      My JumpList control is quite a bit more user-friendly, with the LongListSelector you have to structure / group the data yourself, as described in this blog post. Also, my control is more ‘sexy’, LongListSelector does not have animated effects for the tiles, there is a blog post that describes adding animations to the LongListSelector, but it does not work on a real phone ;-) … the animations are jumpy and stutter!

      The LongListSelector does however have a slight advantage in initial render speed, this is because it implements its own approach to virtualization from the ground-up, whereas my JumpList relies on ItemControl + VirtualizingStackPanel.

      Hope that helps, Colin E.

  31. A Windows Phone 7 Jump List Control | Colin Eberhardt’s Adventures in WPF…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

Leave a Reply