How to display data in a grouped list in LongListSelector for Windows Phone 8

[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]

This topic describes how you can display data as a grouped list in a LongListSelector control. The example in this topic displays address book entries that are grouped by the first letter of the last name. When you click on a group header, a jump list with all letters of the alphabet appears, which the user can use to navigate to a particular group in the LongListSelector.

This topic contains the following sections.

Adding the LongListSelector control to your project

The easiest way to add a LongListSelector control and reference it properly is to drag it from the Toolbox and drop it to your XAML designer or XAML view.

To add the LongListSelector control

  1. In Visual Studio, create a new Windows Phone App project named LLSSample that targets Windows Phone OS 8.0.

  2. In the LLSSample project, open the Toolbox, and then click Common Controls.

  3. From the Toolbox, drag the LongListSelector control to the XAML view.

    <!--ContentPanel - place additional content here-->
    <Grid> 
       <phone:LongListSelector x:Name="AddrBook"/>
    </Grid>
    

Creating the AlphaKeyGroup class

AlphaKeyGroup is a helper class that is used to convert a flat list of data into a grouped list in which the entries are grouped by a key. In this example we use this class to convert a flat list of address book entries to a list of lists that is grouped by the first letter of the last name.

To create the AlphaKeyGroup class

  1. In the Solution Explorer, right-click the LLSSample project, click Add, and then click class.

  2. In the Add New Item dialog, in the Name box, type AlphaKeyGroup.cs, and then click Add.

  3. In the AlphaKeyGroup class, copy and paste the following code.

    using System.Collections.Generic;
    using System.Globalization;
    using Microsoft.Phone.Globalization;
    
    namespace LLSSample
    {
        public class AlphaKeyGroup<T> : List<T>
        {
            /// <summary>
            /// The delegate that is used to get the key information.
            /// </summary>
            /// <param name="item">An object of type T</param>
            /// <returns>The key value to use for this object</returns>
            public delegate string GetKeyDelegate(T item);
    
            /// <summary>
            /// The Key of this group.
            /// </summary>
            public string Key { get; private set; }
    
            /// <summary>
            /// Public constructor.
            /// </summary>
            /// <param name="key">The key for this group.</param>
            public AlphaKeyGroup(string key)
            {
                Key = key;
            }
    
            /// <summary>
            /// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping.
            /// </summary>
            /// <param name="slg">The </param>
            /// <returns>Theitems source for a LongListSelector</returns>
            private static List<AlphaKeyGroup<T>> CreateGroups(SortedLocaleGrouping slg)
            {
                List<AlphaKeyGroup<T>> list = new List<AlphaKeyGroup<T>>();
    
                foreach (string key in slg.GroupDisplayNames)
                {
                    list.Add(new AlphaKeyGroup<T>(key));
                }
    
                return list;
            }
    
            /// <summary>
            /// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping.
            /// </summary>
            /// <param name="items">The items to place in the groups.</param>
            /// <param name="ci">The CultureInfo to group and sort by.</param>
            /// <param name="getKey">A delegate to get the key from an item.</param>
            /// <param name="sort">Will sort the data if true.</param>
            /// <returns>An items source for a LongListSelector</returns>
            public static List<AlphaKeyGroup<T>> CreateGroups(IEnumerable<T> items, CultureInfo ci, GetKeyDelegate getKey, bool sort)
            {
                SortedLocaleGrouping slg = new SortedLocaleGrouping(ci);
                List<AlphaKeyGroup<T>> list = CreateGroups(slg);
    
                foreach (T item in items)
                {
                    int index = 0;
                    if (slg.SupportsPhonetics)
                    {
                        //check if your database has yomi string for item
                        //if it does not, then do you want to generate Yomi or ask the user for this item.
                        //index = slg.GetGroupIndex(getKey(Yomiof(item)));
                    }
                    else
                    {
                        index = slg.GetGroupIndex(getKey(item));
                    }
                    if (index >= 0 && index < list.Count)
                    {
                        list[index].Add(item);
                    }
                }
    
                if (sort)
                {
                    foreach (AlphaKeyGroup<T> group in list)
                    {
                        group.Sort((c0, c1) => { return ci.CompareInfo.Compare(getKey(c0), getKey(c1)); });
                    }
                }
    
                return list;
            }
    
        }
    }
    

Creating a grouped list of data

In this section, first you create a flat list of address book entries, and then you convert the flat list into a grouped list.

To create a flat list of data

  1. In MainPage.xaml.cs, add the following class named AddressBook. This class represents an address book entry.

    public class AddressBook
    {
       public string FirstName
       {
          get;
          set;
       }
             public string LastName
       {
          get;
          set;
       }
             public string Address
       {
          get;
          set;
       }
             public string Phone
       {
          get;
          set;
       }
    
       public AddressBook(string firstname, string lastname, string address, string phone)
       {
          this.FirstName = firstname;
          this.LastName = lastname;
          this.Address = address;
          this.Phone = phone;
       }
    }
    
  2. In the MainPage() constructor, add the following code to create a List<(Of <(T>)>) named source, and then add some address book entries.

    List<AddressBook> source = new List<AddressBook>();
    source.Add(new AddressBook ("Joe", "Smith", "US", "48579347594"));
    source.Add(new AddressBook("Jim", "Johnson", "UK", "3423423423"));
    source.Add(new AddressBook("Mary", "Robert", "India", "9384394793"));
    source.Add(new AddressBook("Patricia", "James", "France", "9384394793"));
    source.Add(new AddressBook("Linda", "Williams", "Italy", "9384394793"));
    source.Add(new AddressBook("David", "Jones", "US", "9384394793"));
    source.Add(new AddressBook("Elizabeth", "Martinez", "US", "9384394793"));
    source.Add(new AddressBook("Richard", "Robinson", "Germany", "9384394793"));
    source.Add(new AddressBook("Charles", "Clark", "US", "9384394793"));
    source.Add(new AddressBook("Joseph", "Rodriguez", "France", "9384394793"));
    source.Add(new AddressBook("Susan", "Lewis", "Italy", "9384394793"));
    source.Add(new AddressBook("Thomas", "Lee", "US", "9384394793"));
    source.Add(new AddressBook("Margaret", "Walker", "US", "9384394793"));
    source.Add(new AddressBook("Christopher", "Hall", "UK", "9384394793"));
    source.Add(new AddressBook("Lisa", "Allen", "US", "9384394793"));
    source.Add(new AddressBook("Daniel", "Young", "US", "9384394793"));
    source.Add(new AddressBook("Paul", "Hernandez", "US", "9384394793"));
    source.Add(new AddressBook("Karen", "King", "US", "9384394793"));
    source.Add(new AddressBook("Ruth", "Wright", "US", "9384394793"));
    source.Add(new AddressBook("Steven", "Lopez", "US", "9384394793"));
    source.Add(new AddressBook("Edward", "Hill", "US", "9384394793"));
    source.Add(new AddressBook("Sharon", "Scott", "US", "9384394793"));
    source.Add(new AddressBook("Brian", "Green", "US", "9384394793"));
    source.Add(new AddressBook("Michelle", "Ramos", "US", "9384394793"));
    source.Add(new AddressBook("Ronald", "Mason", "India", "9384394793"));
    source.Add(new AddressBook("Laura", "Crawford", "US", "9384394793"));
    source.Add(new AddressBook("Anthony", "Burns", "US", "9384394793"));
    source.Add(new AddressBook("Sarah", "Gordon", "India", "9384394793"));
    source.Add(new AddressBook("Kevin", "Hunter", "US", "9384394793"));
    source.Add(new AddressBook("Kimberly", "Tucker", "US", "9384394793"));
    source.Add(new AddressBook("Jason", "Dixon", "US", "9384394793"));
    source.Add(new AddressBook("Deborah", "Mills", "US", "9384394793"));
    source.Add(new AddressBook("Matthew", "Warren", "US", "9384394793"));
    source.Add(new AddressBook("Jessica", "Nichols", "US", "9384394793"));
    source.Add(new AddressBook("Gary", "Knight", "US", "9384394793"));
    source.Add(new AddressBook("Shirley", "Ferguson", "US", "9384394793"));
    

To convert a flat list of data into a list of lists grouped by a key

  1. In the MainPage() constructor, add the following code to create a grouped list of address book entries named DataSource. The entries in DataSource are grouped by the first letter of the last name.

    List<AlphaKeyGroup<AddressBook>> DataSource = AlphaKeyGroup<AddressBook>.CreateGroups(source, 
                    System.Threading.Thread.CurrentThread.CurrentUICulture,
                    (AddressBook s) => { return s.LastName; }, true);
    

    In this code, the CreateGroups() method is used to group the entries in source. CreateGroup() compares the entries in source to the alphabets of the phone’s UI culture and sorts them by the first letter of the last name.

  2. Data bind the grouped list to the source of the LongListSelector control.

    AddrBook.ItemsSource = DataSource;
    

Displaying the grouped data in LongListSelector

In this section, ItemTemplate and GroupHeaderTemplate properties are used to display the grouped data in the LongListSelector control, and JumpListStyle property is used to define the style of the jump list that is displayed when the user presses a group header.

To display the grouped data

  1. In MainPage.xaml, add the IsGroupingEnabled, HideEmptyGroups, ItemTemplate, and GroupHeaderTemplate properties to the LongListSelector element as shown in the following code.

    <phone:LongListSelector
      x:Name="AddrBook"
      JumpListStyle="{StaticResource AddrBookJumpListStyle}"
      Background="Transparent"
      GroupHeaderTemplate="{StaticResource AddrBookGroupHeaderTemplate}"
      ItemTemplate="{StaticResource AddrBookItemTemplate}"
      LayoutMode="List"
      IsGroupingEnabled="true"
      HideEmptyGroups ="true"/>
    

    In this code, LayoutMode is set to List, which means that the address book entries are laid out in a list format. The IsGroupingEnabled is set to true to group the displayed items, and the HideEmptyGroups is set to true, which means that if a group does not have any items in it, it will not be displayed. GroupHeaderTemplate is bound to the DataTemplate class, which defines the look of the group header, and ItemTemplate is bound to the DataTemplate that defines the look of each address book item.

  2. In the <phone:PhoneApplicationPage> element, add the following code to define DataTemplate for the address book items.

    Place this new <phone:PhoneApplicationPage.Resources> section above the Grid named LayoutRoot to ensure that the resources defined here are available to the UI elements on the page.

    <phone:PhoneApplicationPage.Resources>
       <DataTemplate x:Key="AddrBookItemTemplate">
          <StackPanel VerticalAlignment="Top">
             <TextBlock FontWeight="Bold"  Text="{Binding FirstName}" />
             <TextBlock Text="{Binding LastName}" />
             <TextBlock Text="{Binding Address}" />
             <TextBlock Text="{Binding Phone}" />
          </StackPanel>
       </DataTemplate>
    </phone:PhoneApplicationPage.Resources>
    
  3. In the <phone:PhoneApplicationPage.Resources> element, add the following code to define DataTemplate for the group header. In this example, the group header is the first letter of the last name.

    <DataTemplate x:Key="AddrBookGroupHeaderTemplate">
       <Border Background="Transparent" Padding="5">
          <Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62" 
             Height="62" Margin="0,0,18,0" HorizontalAlignment="Left">
             <TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6" 
                FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/>
          </Border>
        </Border>
    </DataTemplate>
    

To display the jump list

  • In the <phone:PhoneApplicationPage.Resources> element, add the following code to define the jump list style.

    <phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter"/>
    <phone:JumpListItemForegroundConverter x:Key="ForegroundConverter"/>
    <Style x:Key="AddrBookJumpListStyle" TargetType="phone:LongListSelector">
       <Setter Property="GridCellSize"  Value="113,113"/>
       <Setter Property="LayoutMode" Value="Grid" />
       <Setter Property="ItemTemplate">
          <Setter.Value>
             <DataTemplate>
                <Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="113" Height="113" Margin="6" >
                   <TextBlock Text="{Binding Key}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6" 
                   Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"/>
                </Border>
             </DataTemplate>
           </Setter.Value>
        </Setter>
    </Style>
    

    The following illustration displays the LongListSelector control created in this topic.

See Also

Reference

LongListSelector

Other Resources

LongListSelector control design guidelines for Windows Phone