Click here to Skip to main content
15,879,535 members
Articles / Desktop Programming / WPF

A Simple WP7 JumpList in WPF

Rate me:
Please Sign up or sign in to vote.
4.81/5 (12 votes)
22 May 2011CPOL3 min read 40.9K   836   26   10
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.

C#
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.

C#
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.

C#
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.
    C#
    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.
    C#
    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.

C#
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.

C#
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.

XML
<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)


Written By
Software Developer
United States United States
An individual with more than a decade of experience in desktop computing and mobile app development primarily on the Microsoft platform. He loves programming in C#, WPF & XAML related technologies.
Current interests include web application development, developing rich user experiences across various platforms and exploring his creative side.

Ratish's personal blog: wpfspark.wordpress.com

Comments and Discussions

 
QuestionThis is work as in windows phone using touch Pin
Member 1057912218-Jan-16 1:16
Member 1057912218-Jan-16 1:16 
QuestionSilverlight version works Pin
Member 165621431-Oct-11 7:46
Member 165621431-Oct-11 7:46 
AnswerRe: Silverlight version works Pin
Ratish Philip1-Nov-11 1:05
Ratish Philip1-Nov-11 1:05 
QuestionNice job Pin
Member 165621421-Sep-11 10:54
Member 165621421-Sep-11 10:54 
AnswerRe: Nice job Pin
Ratish Philip25-Sep-11 1:44
Ratish Philip25-Sep-11 1:44 
GeneralMy vote of 5 Pin
Filip D'haene26-May-11 8:47
Filip D'haene26-May-11 8:47 
GeneralRe: My vote of 5 Pin
Ratish Philip26-May-11 15:28
Ratish Philip26-May-11 15:28 
GeneralNice navigational aid Pin
Nic_Roche23-May-11 13:57
professionalNic_Roche23-May-11 13:57 
GeneralRe: Nice navigational aid Pin
Ratish Philip23-May-11 14:34
Ratish Philip23-May-11 14:34 
GeneralRe: Nice navigational aid Pin
Nic_Roche24-May-11 11:42
professionalNic_Roche24-May-11 11:42 

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

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