Click here to Skip to main content
Click here to Skip to main content

A Simple WP7 JumpList in WPF

, 22 May 2011
Rate this:
Please Sign up or sign in to vote.
Recreating the Windows Phone 7 JumpList in WPF

Introduction

I am deeply impressed by Metro UI, the typography based design created by Microsoft. It is very clean and fast. In this article, I am demonstrating a simple example of how a WP7 JumpList can be created in WPF. The WP7 JumpList was demonstrated in the MIX '11 event.

WP7 JumpList Image

Using the Code

The WPF JumpList control is composed of two controls:

  • IndexControl - used to display the indices.
  • JumpListControl - encapsulates the contents of the JumpList.

IndexControl

The IndexControl is used to display the index in the ValuesPanel as well as the JumpListPanel. It has a dependency property IndexValue which is used to display the index value in the IndexControl.

public static readonly DependencyProperty IndexValueProperty =
    DependencyProperty.Register("IndexValue", typeof(string), typeof(IndexControl),
        new FrameworkPropertyMetadata
        ((new PropertyChangedCallback(OnIndexValueChanged))));

The IndexControl also has a dependency property IndexState to define its state.

public static readonly DependencyProperty IndexStateProperty =
    DependencyProperty.Register("IndexState", 
    typeof(IndexStateType), typeof(IndexControl),
    new FrameworkPropertyMetadata(IndexStateType.ListDisplay, 
    (new PropertyChangedCallback(OnIndexStateChanged))));

There are three states, defined by the enum IndexStateType.

public enum IndexStateType
{
    // The state when the IndexControl is displayed in the long list.
    ListDisplay,
    // The state when the IndexControl is displayed in the JumpList 
    // and this index has NO values
    IndexNotFound,
    // The state when the IndexControl is displayed in the JumpList 
    // and this index has values
    IndexFound
}

Based on its state, the look and feel of the IndexControl changes.

IndexState Types

JumpListControl

The WPF JumpList control has two panels:

  • ValuesPanel - used to display the values (names) in a long list format.
  • JumpListPanel - used to display the indices.

At any given instance, only one of the above panels is visible in the JumpListControl, while the other panel remains hidden.

ValuesPanel

WPF JumpList Image

The ValuesPanel displays the values (or names) in a long list format. For each index, the IndexControl and the set of Names are encapsulated in a StackPanel and added to the parent StackPanel.

Values Panel Image

JumpListPanel

WPF JumpList Image

The JumpListPanel consists of a WrapPanel in which the IndexControls are added.

JumpList Panel Image

The JumpListPanel defines two dependency properties:

  • Values - ObservableCollection<string> - serves as an input for the control.
    public static readonly DependencyProperty ValuesProperty =
        DependencyProperty.Register("Values", 
        typeof(ObservableCollection<string>), typeof(JumpListControl),
        new FrameworkPropertyMetadata
        ((new PropertyChangedCallback(OnValuesChanged))));
  • SelectedValue - indicates the value (or Name) selected by the user.
    public static readonly DependencyProperty SelectedValueProperty =
        DependencyProperty.Register("SelectedValue", 
        typeof(string), typeof(JumpListControl),
        new FrameworkPropertyMetadata
        ((new PropertyChangedCallback(OnSelectedValueChanged))));

When the JumpListControl is initialized, it adds IndexControls, to the JumpListPanel, for the indices a-z. The state of each of the IndexControls is set to IndexNotFound.

public JumpListControl()
{
    InitializeComponent();

    JumpListScrollView.Visibility = System.Windows.Visibility.Hidden;

    foreach (char idx in indexes)
    {
        IndexControl idxCtrl = new IndexControl
        {
            Width = 50,
            Height = 50,
            IndexValue = idx.ToString(),
            IndexState = IndexStateType.IndexNotFound,
            Margin = new Thickness(4, 4, 0, 0)
        };

        idxCtrl.MouseLeftButtonDown += 
            new MouseButtonEventHandler(OnIndexClickedInJumpList);

        JumpListPanel.Children.Add(idxCtrl);
    }
}

When the Values dependency property is set by the user, the JumpListControl parses the list and creates the indexed long list in the ValuesPanel and changes the state of the IndexControls, in the JumpListPanel, from IndexNotFound to IndexFound.

private void Parse(ObservableCollection<string> values)
{
    Dictionary<string, List<string>> valueDict = new Dictionary<string, List<string>>();

    List<string> valueList = values.ToList();

    // Sort the values
    valueList.Sort();

    // Get the distinct indexes
    foreach (string str in valueList)
    {
        string key = Char.ToLower(str[0]).ToString();
        if (!valueDict.ContainsKey(key))
        {
            valueDict[key] = new List<string>();
        }
        valueDict[key].Add(str);
    }

    // Set the IndexState of all the IndexControls 
    // whose index has been found as IndexFound
    JumpListPanel.Children.OfType<IndexControl>()
                          .Where(i => valueDict.Keys.Contains(i.IndexValue))
                          .All(i =>
                          {
                              i.IndexState = IndexStateType.IndexFound;
                              return true;
                          });


    // Add the index and the related names to the Values Panel
    foreach (string key in valueDict.Keys)
    {
        StackPanel stkPanel = new StackPanel 
	{ HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch };

        IndexControl idxCtrl = new IndexControl
        {
            Width = 50,
            Height = 50,
            IndexValue = key,
            IndexState = IndexStateType.ListDisplay,
            Margin = new Thickness(4),
            HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
            VerticalAlignment = System.Windows.VerticalAlignment.Center
        };

        idxCtrl.MouseLeftButtonDown += 
		new MouseButtonEventHandler(OnIndexClickedInValuesPanel);

        stkPanel.Children.Add(idxCtrl);

        foreach (string str in valueDict[key])
        {
            TextBlock tb = new TextBlock
            {
                FontFamily = font,
                FontWeight = FontWeights.Light,
                FontSize = 22,
                Foreground = Brushes.White,
                TextAlignment = TextAlignment.Left,
                Margin = new Thickness(4, 4, 0, 0),
                Text = str,
                HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                VerticalAlignment = System.Windows.VerticalAlignment.Center
            };

            tb.MouseLeftButtonDown += new MouseButtonEventHandler(OnValueSelected);

            stkPanel.Children.Add(tb);
        }

        ValuesPanel.Children.Add(stkPanel);
    }
}

When the ValuesPanel is being displayed and the user clicks on any of the indices, then the ValuesPanel is hidden and the JumpListPanel is displayed. When the user clicks on any of the indices in the JumpListPanel, the JumpListPanel is hidden, the ValuesPanel is displayed and the ValuePanel scrolls to the index selected by the user.

Clicking on any of the Names will set the SelectedValue property of the JumpListControl.

EndPoint

What I have attempted here is a basic implementation of the JumpList control which accepts a list of strings as input. It can be further modified to accept a collection of objects (say a person's record) and an image can be displayed alongside each name in the ValuesPanel.

Points of Interest

An important lesson I learnt during the development of this control is that when you are adding items to a WrapPanel (say with Orientation=Horizontal) and the items extend beyond the height of the WrapPanel, then the vertical scrollbar will not appear automatically (even though you set ScrollViewer.VerticalScrollBarVisibility="Auto").

To overcome this problem, you need to wrap your WrapPanel with a ScrollViewer.

<ScrollViewer Name="JumpListScrollView"
              HorizontalScrollBarVisibility="Disabled"
              VerticalScrollBarVisibility="Auto">
    <WrapPanel Name="JumpListPanel"
               Orientation="Horizontal">
    </WrapPanel>
</ScrollViewer>

History

  • 22nd May, 2010 - Version 1.0 released

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ratish Philip
Software Developer NA
India India
Ratish Philip is a software developer with 8 years of experience. He loves programming in C#, WPF & Silverlight.
 
He is currently exploring the depths of Windows 8 programming.
 
Creating enriched user experiences is what appeals to him the most.
 
Occasionally expresses his creativity through pencil sketching too!
 
Ratish's personal blog: wpfspark.wordpress.com

Comments and Discussions

 
QuestionSilverlight version works [modified] PinmemberMember 165621431-Oct-11 7:46 
AnswerRe: Silverlight version works PinmemberRatish Philip1-Nov-11 1:05 
QuestionNice job PinmemberMember 165621421-Sep-11 10:54 
AnswerRe: Nice job PinmemberRatish Philip25-Sep-11 1:44 
GeneralMy vote of 5 PinmemberFilip D'haene26-May-11 8:47 
GeneralRe: My vote of 5 PinmemberRatish Philip26-May-11 15:28 
GeneralNice navigational aid PinmemberNic_Roche23-May-11 13:57 
GeneralRe: Nice navigational aid PinmemberRatish Philip23-May-11 14:34 
GeneralRe: Nice navigational aid PinmemberNic_Roche24-May-11 11:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140814.1 | Last Updated 22 May 2011
Article Copyright 2011 by Ratish Philip
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid