Windows Phone 8的列表控件天生支持分组,就像人脉应用中的类似,可以快速根据拼音首字母定位。在列表视图中点击分组标题后显示所有的组名,点击组名即可定位到这个组。我们自己开发的WP应用也能做到这样的分组功能,但需要一些额外的代码。下面的例子来自我的一个WP应用,有图有真相:

分组视图:

实现LongListSelector分组其实很简单。
1. 首先,你需要一个分组的助手类,这是一个相对标准的类,MSDN上抄来的:
public class Group<T> : List<T>
{
public Group(string name, IEnumerable<T> items)
: base(items)
{
this.Title = name;
}
public string Title
{
get;
set;
}
public 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();
}
}
然后,对于你要分组的内容,就能通过getKeyFunc委托来指定依据哪个字段分组了。比如我应用里的电影列表希望根据电影名称进行分组,即MovieInfo.Title,代码就要这样写:
this.GroupedQueryResults = Group<MovieInfo>.GetItemGroups(rawCollection, m => m.Title).ToObservableCollection();
其中,rawCollection是一个未经过分组的IEnumerable<MovieInfo>列表。
2. 在XAML页面里,LongListSelector所绑定的对象需要设置为经过分组的GroupedQueryResults。
<phone:LongListSelector ItemsSource="{Binding GroupedQueryResults, Mode=TwoWay}"
LayoutMode="List"
IsGroupingEnabled="True"
HideEmptyGroups="True"
JumpListStyle="{StaticResource MovieListJumpListStyle}"
>
IsGroupingEnabled属性必须设置为true,以启用分组功能。
HideEmptyGroups属性为是否隐藏没有数据的组,true为不显示,false为显示。
JumpListStyle是分组视图的样式,我的应用里样式定义如下:
<Style x:Key="MovieListJumpListStyle" TargetType="phone:LongListSelector">
<!--<Setter Property="GridCellSize" Value="113,113"/>-->
<Setter Property="LayoutMode" Value="List" />
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border Background="{Binding Converter={StaticResource BackgroundConverter}}" Width="400" Height="90" Margin="6" >
<TextBlock Text="{Binding Title}"
FontFamily="{StaticResource PhoneFontFamilySemiBold}"
FontSize="30"
Padding="6"
Foreground="{Binding Converter={StaticResource ForegroundConverter}}"
VerticalAlignment="Center"/>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
最后,我们还需要指定列表视图中组标题的模板。我的模板如下:
<phone:LongListSelector.GroupHeaderTemplate>
<DataTemplate>
<Border Background="Transparent" Padding="5">
<Border
Background="{StaticResource PhoneAccentBrush}"
BorderBrush="{StaticResource PhoneAccentBrush}"
BorderThickness="2"
Height="62"
Margin="0,20,0,5"
HorizontalAlignment="Left">
<TextBlock Text="{Binding Title}"
Foreground="{StaticResource PhoneForegroundBrush}"
FontSize="36"
Padding="6"
FontFamily="{StaticResource PhoneFontFamilySemiLight}"
HorizontalAlignment="Left"
VerticalAlignment="Center"/>
</Border>
</Border>
</DataTemplate>
</phone:LongListSelector.GroupHeaderTemplate>
注意代码里的“{Binding Title}”,这个绑定的就是组名,即刚才Group<T>类里面的Title属性,如果你不希望它叫Title可以直接改Group<T>类。