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