Olá pessoal, tudo bom?
Neste post explico como criar uma lista de carros, por exemplo, agrupada por letras usando o componente LongListSelector do XAML. O trabalho é um pouco árduo, mas vou tentar simplificar as coisas. Vamos a elas:

1º passo: Criar uma classe em seu projeto para fazer a ordenação e agrupamento dos itens (AlphaKeyGroup.cs)
Essa classe chama-se AlphaKeyGroup<T> e representa a letra do alfabeto e todos os itens que iniciam com ela. Essa classe não é parte do SDK do Windows Phone, por isso, teremos que digitá-la e manualmente adiciona-la ao nosso projeto. Para facilitar, faça o download da classe aqui.
using Microsoft.Phone.Globalization;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ListByLetter
{
public class AlphaKeyGroup<T> : List<T>
{
/// <summary>
/// O delegate que é usado para obter a informação da chave
/// </summary>
/// <param name="item">Um objeto do tipo T</param>
/// <returns>O valor da chave usado para esse objeto</returns>
public delegate string GetKeyDelegate(T item);
/// <summary>
/// A chave deste grupo
/// </summary>
public string Key { get; private set; }
/// <summary>
/// Construtor público
/// </summary>
/// <param name="key"></param>
public AlphaKeyGroup(string key)
{
Key = key;
}
/// <summary>
/// Cria uma lista de AlphaKeyGroup<T> com chaves "setadas" por um SortedLocaleGrouping
/// </summary>
/// <param name="slg"></param>
/// <returns>Fonte de dados para o 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>
/// Cria uma lista de AlphaGroup<T> com as chaves "setadas" por um SortedLocaleGrouping
/// </summary>
/// <param name="items">Os itens a serem colocados em grupo</param>
/// <param name="ci">A CultureInfo para ordenar e agrupar</param>
/// <param name="getKey">Um delegate para pegar a chave de um item</param>
/// <param name="sort">Irá ordenar os dados se for "true"</param>
/// <returns>Uma fonte de dados para o 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)
{
//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;
}
}
}
2º passo: Preparar a classe que representará os dados para teste
Nesse passo declaramos uma classe Car para posteriormente representarmos uma lista de carros a serem exibidos através do LongListSelector. Vejamos a classe Car.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ListByLetter
{
public class Car
{
public string Name { get; set; }
public int Year { get; set; }
public string Brand { get; set; }
}
}
Agora, para popular nossa lista de carros vamos utilizar o próprio construtor da MainPage.xaml.cs. Veja o código abaixo:
public MainPage()
{
InitializeComponent();
this.Loaded += MainPage_Loaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
List<Car> cars = new List<Car>();
cars.Add(new Car { Name = "Fusca", Year = 1972, Brand = "VW" });
cars.Add(new Car { Name = "Frontier", Year = 2009, Brand = "Nissan" });
cars.Add(new Car { Name = "C3", Year = 2012, Brand = "Citroen" });
cars.Add(new Car { Name = "Corolla", Year = 2009, Brand = "Toyota" });
cars.Add(new Car { Name = "Uno", Year = 2002, Brand = "Fiat" });
cars.Add(new Car { Name = "Ford Modelo A", Year = 1929, Brand = "Ford" });
cars.Add(new Car { Name = "Fusca", Year = 1982, Brand = "VW" });
cars.Add(new Car { Name = "Symbol", Year = 2009, Brand = "Renault" });
cars.Add(new Car { Name = "Palio", Year = 2007, Brand = "Fiat" });
cars.Add(new Car { Name = "Civic", Year = 2007, Brand = "Honda" });
cars.Add(new Car { Name = "Camaro", Year = 2014, Brand = "Chevrolet" });
cars.Add(new Car { Name = "Monza", Year = 1985, Brand = "Chevrolet" });
List<AlphaKeyGroup<Car>> list = AlphaKeyGroup<Car>.CreateGroups(cars, Thread.CurrentThread.CurrentUICulture, c => c.Brand, true);
llsCars.ItemsSource = list; //Ver comentário abaixo
}
O objeto llsCars corresponde ao LongListSelector que será declarado mais à frente…
3° passo: Definição do LongListSelector e seus respectivos recursos – XAML
Em relação ao desenvolvimento XAML temos que declarar o LongListSelector e mais alguns Resources para a página onde o mesmo será exibido, em nosso caso, na própria MainPage.xaml.
Teremos que definir um DataTemplate para quando a lista agrupada por letras estiver em modo de exibição de seus itens e um estilo para quando o LongListSelector estiver em modo de seleção de suas opções. Devemos reparar que na definição do estilo estaremos usando dois converters chamados de JumpListItemBackgroundConverter e JumpListItemForegroundConverter, sendo que os mesmos são usados para identificar os grupos de letras que não possuem itens, ou seja, devem aparecer em cinza para que o usuário já perceba que ali não há itens a serem exibidos. Caso contrário, os grupos de letras serão exibidos em branco com o fundo de acordo com o phone accent color.
Ainda em relação aos recursos da página, teremos outro DataTemplate que irá dizer para para o LongListSelector a forma como os dados dos carros deverão ser apresentados. Vamos às definições:
...
<!-- Definição dos recursos para a página -->
<phone:PhoneApplicationPage.Resources>
<!-- Definição do template para apresentação da lista em modo de exibição -->
<DataTemplate x:Key="CarsGroupHeaderTemplate">
<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>
<!-- Definição dos converters para os grupos de letras que não possuem itens -->
<phone:JumpListItemBackgroundConverter x:Key="BackgroundConverter" />
<phone:JumpListItemForegroundConverter x:Key="ForegroundConverter" />
<!-- Definição do estilo para quando o LongListSelector estiver em modo de pesquisa -->
<Style x:Key="CarsJumpListStyle" 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>
<!-- Definição do template para exibição da lista de carros -->
<DataTemplate x:Key="CarsItemTemplate">
<StackPanel Orientation="Horizontal" Tap="StackPanel_Tap">
<TextBlock Text="{Binding Brand}" FontSize="30" />
<TextBlock Text="{Binding Name}" Margin="10,0,0,0" FontSize="30" />
<TextBlock Text="{Binding Year}" Margin="10,0,0,0" FontSize="30" />
</StackPanel>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
...
Por fim, devemos agora declarar o próprio LongListSelector e indicar a ele todos os recursos a serem utilizados. Vejamos:
...
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:LongListSelector x:Name="llsCars"
IsGroupingEnabled="True"
HideEmptyGroups="True"
GroupHeaderTemplate="{StaticResource CarsGroupHeaderTemplate}"
ItemTemplate="{StaticResource CarsItemTemplate}"
JumpListStyle="{StaticResource CarsJumpListStyle}" />
</Grid>
...
Agora basta executar e visualizar o resultado. Fácil, não? 🙂
Grande abraço !
Eduardo Henrique Rizo
Post Relacionado:
![]()
[twitter-follow screen_name=’eduardorizo’ show_count=’yes’]
Pingback: Free: Curso Windows Phone – Vários tópicos | Blog do Eduardo H. Rizo
o Microsoft.Phone.Globalization na alfakey AlphaKeyGroup não existe. Como adiciono?
Olá, tudo bom?
Esse namespace é para APPs Windows Phone Silverlight. Sua APP está nesse formato?
[]s
Eduardo H. Rizo