The New LongListSelector control in Windows Phone 8 SDK in depth

published on: 03/01/2020

by WindowsPhoneGeek

The LongListSelector implements a jump-list style of UI as seen in the address book of the phone. This type of UI is usually used to display long lists of data. Up until now, if you wanted to use a LongListSelector control in your app, you had to use an implementation of this control from a library like the Windows Phone Toolkit. This changes with Windows Phone 8, since a LongListSelector control is now included in the SDK. In this article we will demonstrate how to use this control, as well as share some important tips for porting apps that use the LongListSelector from the Windows Phone Toolkit.

The new LongListSelect control that is now part of the Windows Phone 8 SDK, implements full UI and data virtualization. In fact, it is recommended that you use the LongListSelector instead of the ListBox control, whenever you want to display lists of data, even if the data does not need to be grouped.

NOTE: Those of you, who are new to Windows Phone, can think of the LongListSelector as an advanced ListBox that can display both flat and grouped lists. It helps users to navigate through long lists of data, by allowing them to jump between different sections of the list using a quick jump grid that overlays the list when the user selects one of the group headers.

NOTE: The new LongListSelector is different than the well-known Windows Phone Toolkit LongListSelector. Although they may look similar at first sight, the new control exposes different properties, has different data source requirements and is used in a slightly different way.

Visual structure

In the following diagrams you can see the visual structure of the LongListSelector control:

NOTE: You can use the LayoutMode property of the JumpListStyle to display the group headers either in a list or grid layout.

Data source requirements

We will create a sample app that displays information about different cities grouped by country.

To generate the data source we will use the following method:

private static IEnumerable<City> GetCityList() { List<City> cityList = new List<City>(); cityList.Add(new City() { Name = "Milan", Country = "IT", Language = "Italian", Flag = new Uri(@"/Images/Italy.png", UriKind.Relative) }); cityList.Add(new City() { Name = "Roma", Country = "IT", Language = "Italian", Flag = new Uri(@"/Images/Italy.png", UriKind.Relative) }); cityList.Add(new City() { Name = "Madrid", Country = "ES", Language = "Spanish", Flag = new Uri(@"/Images/Spain.png", UriKind.Relative) }); //.. return cityList; }

Where City is a basic class that exposes the following properties:

To prepare the list of cities to be displayed with the LongListSelector control we will use the following code to group the cities by country:

private List<Group<City>> GetCityGroups() { IEnumerable<City> cityList = GetCityList(); return GetItemGroups(cityList, c => c.Country); } private static List<Group<T>> GetItemGroups<T>(IEnumerable<T> itemList, Func<T, string> getKeyFunc) { IEnumerable<Group<T>> groupList = from item in itemList group item by getKeyFunc(item) into g orderby g.Key select new Group<T>(g.Key, g); return groupList.ToList(); }

NOTE: While the LongListSelector control from the Windows Phone Toolkit worked fine with data sources that only implement IEnumerable, the new control requires IList. This is why our GetCityGroups method returns List and the Group class in the following code snippet inherits List<T> as well. On the other side, overriding Equals is no longer required for the correct operation of the jump list. As a result we end up with a very simple Group class:

public class Group<T> : List<T> { public Group(string name, IEnumerable<T> items) : base(items) { this.Title = name; } public string Title { get; set; } }

The UI

We will start building the UI for this example, by defining the templates for all elements that we identified while discussing the visual structure of the LongListSelector control.

GroupHeaderTemplate - this template defines how the group headers look:

<DataTemplate x:Key="groupHeaderTemplate"> <Border Width="72" Height="72" HorizontalAlignment="Left" Background="{Binding Converter={StaticResource BackgroundConverter}}" Margin="6"> <TextBlock Text="{Binding Title}" FontSize="40" Padding="6" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="{Binding Converter={StaticResource ForegroundConverter}}" /> </Border> </DataTemplate>

ItemTemplate - this template defines how list items look:

<DataTemplate x:Key="citiesItemTemplate"> <StackPanel Orientation="Horizontal"> <Image Source="{Binding Flag}" Height="50" Margin="0,0,10,0"/> <StackPanel> <TextBlock Text="{Binding Name, StringFormat='City: {0}'}" FontSize="26" /> <TextBlock Text="{Binding Language, StringFormat='Language: {0}'}" Style="{StaticResource PhoneTextSubtleStyle}" /> </StackPanel> </StackPanel> </DataTemplate>

JumpListStyle - this template defines how the jump list looks:

<Style x:Key="LongListSelectorJumpListStyle" 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 Title}" FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="48" Padding="6" Foreground="{Binding Converter={StaticResource ForegroundConverter}}" VerticalAlignment="Center"/> </Border> </DataTemplate> </Setter.Value> </Setter> </Style>

ListHeaderTemplate - this template defines how the list header looks:

<DataTemplate x:Key="citiesListHeader"> <Border Background="White" Opacity="0.2" Height="70"> <TextBlock Text="Cities Header" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black" /> </Border> </DataTemplate>

ListFooterTemplate - this template defines how the list footer looks:

<DataTemplate x:Key="citiesListFooter"> <Border Background="White" Opacity="0.2" Height="70"> <TextBlock Text="Cities Footer" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"/> </Border> </DataTemplate>

Finaly, note that the LongListSelector is placed in the "Microsoft.Phone.Controls" namespace. So, you can declare the control in this way:

<phone:LongListSelector x:Name="longListSelector" IsGroupingEnabled="True" LayoutMode="List" HideEmptyGroups="False" ItemTemplate="{StaticResource citiesItemTemplate}" GroupHeaderTemplate="{StaticResource groupHeaderTemplate}" JumpListStyle="{StaticResource LongListSelectorJumpListStyle}" ListHeaderTemplate="{StaticResource citiesListHeader}" ListFooterTemplate="{StaticResource citiesListFooter}" Margin="1,0,-1,0"/>

NOTE: If JumpListStyle is not set, the jump list will not work!

NOTE: You have to set *IsGroupingEnabled="True"*in order to display the list of items in groups.

NOTE:LayoutModespecifies whether the LongListSelector is in a list mode or grid mode. Finally, in order to display the list of cities, in the MainPage constructor in MainPage.xaml.cs, we set the ItemsSource property of the LongListSelector like this:

this.longListSelector.ItemsSource = this.GetCityGroups();

Conclusion

The LongListSelect control that is now included with the Windows Phone 8 SDK is an efficient implementation of the jump-list style UI and supports full UI and data virtualization. It is actually recommended to use the LongListSelector control instead of ListBox even for displaying flat lists of data. This article demonstrates how to use the new LongListSelector control. We also showed how the data source requirements are different from the LongListSelector control that comes with the Windows Phone Toolkit.

NOTE: This article is a part of the FREE WindowsPhoneGeek Magazine. You can download the magazine as well as the he full source code here: http://windowsphonegeek.com/magazine

You can also follow us on Twitter: @winphonegeek for Windows Phone; @winrtgeek for Windows 8 / WinRT

Comments

raghuraman posted by: excellent on 11/28/2012 14:05:28 thank you for the excellent write up.

Sticky GroupHeader? posted by: akshay2000 on 12/02/2012 08:46:15 Does this control provide option to make GroupHeader sticky? In native Windows Phone apps (like people list) the group header (say letter p) sticks to the top of screen as long as items starting with p are on the screen. LongListSelector in Windows Phone toolkit would scroll the header just like any other item in list. Is stickyheader available now?

ForefroundConverter Not Around posted by: OKP on 12/11/2012 18:42:35 Great write up, much better than what I was going by before. Two things however, is it possible you can point me to a break down of how the group functions/class work as far as the coding? I really want to understand it. Secondly, I'm trying to follow the instructions, and I assume the converters in the item/group definition take care of the current theme. I can't however find the ForegroundConverter. I'm using the new Dev toolkit, but it's not popping into VS. Any help would be great.

ofs posted by: ofs on 12/14/2012 06:47:15 why we use : base(items) ?

Observable posted by: OP on 12/14/2012 23:17:57 Could we still do this with an observable list? And so, how would we?

SelectedItem cannot be set to null posted by: Viswanath on 01/04/2013 02:34:50 I'm having a problem with this implementation. I know that SelectedItem is not bindable, but SelectedIndex is also not exposed. Once I tap on one item, when I come back and tap on it, it does not work. I'm not able to reset the selected item. How do they expect us to use this?

RE: SelectedItem cannot be set to null posted by: poken1151 on 01/23/2013 21:19:12 @Viswanath I had the same issue. What you need to do is set the SelectedItem property to null after you've made the selection. For eg. if you tap an item, in your SelectedItemChange event fuction, do what you need to and the set the SelectedItem property to null: private void listSelectChange(object sender, SelectionChangedEventArgs e) { var listbox = (LongListSelector)sender; if (listbox.SelectedItem == null) return;

posted by: poken1151 on 01/24/2013 20:46:56 Like op said, I'm also interested in finding out how to properly do this with an Observable collection. I want to link this to a contextmenu and have it update when an item deletes. Right now, every time I make a change to the list, I re-assign the itemsource, this can't be the right way to do this. Any help would be welcome.

posted by: Anna on 03/28/2013 15:30:54 I was searching for it since a few days.. thanks!

FooterTemplate posted by: Kumar on 04/26/2013 13:22:42 Hi, I have a TextBlock in the datatemplate of ListFooterTemplate of LongListSelector,to which I give a Collection as Itemssource,I want to bind the Text Property of TextBlock to a string in the Codebehind. Please tell me how to do it. Here is the xaml. I am using VS2012 and WP8 SDK. footertext is the string I have defined in the codebehind. I have implemented INotifyPropertyChanged also but footer doesnt show the text. <phone:LongListSelector ItemsSource="{Binding Collection}"> <phone:LongListSelector .ListFooterTemplate> <DataTemplate> <TextBlock Text= "{Binding footertext}" /> </DataTemplate> </phone:LongListSelector .ListFooterTemplate> </phone:LongListSelector > Thank you

how to pop up? posted by: mun_b on 06/27/2013 22:35:18 How does the LongListSelector pop up? just by tapping on it? or do you I have to keep a button to invoke it?

Search in Longlistselector posted by: EME on 08/25/2013 09:52:49 Is there any sample/help for implementing the search functionality in longlistselector, in the same way as we have in people search in windows phone 8??

XML and longlistselector posted by: Skynet on 09/02/2013 20:20:39 Could you write an article like this for Windows Phone 8: http://www.geekchamp.com/tips/wp7-working-with-xml-reading-filtering-and-databinding

Detailed explanation posted by: Rajeev on 09/27/2013 13:15:07 Thanks for the detailed explanation

no brief explanation posted by: wp8dev on 11/26/2013 07:24:56 this article seems to be not complete one. No brief explanation.