内容简介:Windows Phone版本号自升入8.1以来,开发者就多了一个选项,开发基于WinRT架构的WP或者Universal Windows App。然而开发框架转为WinRT后,很多原有的WP8基于Sliverlight框架的控件和方法变得不再有效,这无疑带来较大的困扰。今天我要讲述的就是此类问题中较易出现的列表拼音分组方案,本文基于WinRT架构予以实现,下面附上实现效果图:
Windows Phone版本号自升入8.1以来,开发者就多了一个选项,开发基于WinRT架构的WP或者Universal Windows App。然而开发框架转为WinRT后,很多原有的WP8基于Sliverlight框架的控件和方法变得不再有效,这无疑带来较大的困扰。今天我要讲述的就是此类问题中较易出现的列表拼音分组方案,本文基于WinRT架构予以实现,下面附上实现效果图:
解决方案:
在WP8下,Silverlight提供了LongListSelector控件,可以方便的实现以上的拼音分组效果,具体实现方法可以参考以下博文:
http://diaosbook.com/Post/2014/2/22/longlistselector-group-by-py-wp8
但是WP8.1则不然,WinRT框架默认不提供分组控件,唯一的解决办法是我们使用相关控件自己来实现。我讲此方案归纳为 SemanticZoom+ListView+GridView+ValueConverter=LongListSelector ,不得不说,这样实现的复杂度远大于Silverlight框架,但其自定义程度高的优势也很明显。
1.数据分组
我们要在正常列表视图下展示分组的列表,这需要我们提前做好数据的分组,对于这一点,官方提供了多种方案,最简单的就是给List中每一项都提供Key属性,这样处理起来最简单,但却十分麻烦,需要我们在数据源里提前设计好Key属性,所以这里我并不会讲述这种分组方法。
我要讲述的是通用程度较高的分组方案,不需要在数据源中设计好Key属性,而是按照正常的方式使用数据源,但是我们会对数据源进行分组处理,最后讲分组后的数据绑定到ListView控件,当然,我们的分组处理行为都是在后台自动处理的。
首先为了ListView控件能够展示分组数据,需要将它的Itemssource绑定到CollectionViewSource数据源,CollectionViewSource数据源IsGrouped属性必须设置为True,Source属性绑定到我们提供的分组数据。
<vm:MainPage_Model x:Name="MainVM" x:Key="DesignVM"/> <CollectionViewSource x:Name="GroupData" x:Key="GroupData" IsSourceGrouped="True" Source="{Binding StartCityGroup, Source={StaticResource DesignVM}}"/>
后台处理:
I. 这里我们创建一个辅助类,参考MSDN的文章方案,我进行了修改适应,实现如下:
//将输入的数据源进行拼音分组,返回CollectionViewSource可以接受的数据结构
public class AlphaKeyGroup<T>:List<T> { const string GlobeGroupKey = "?"; public string Key { get; private set; } //public List<T> this { get; private set; } public AlphaKeyGroup(string key) { Key = key; } private static List<AlphaKeyGroup<T>> CreateDefaultGroups(CharacterGroupings slg) { List<AlphaKeyGroup<T>> list = new List<AlphaKeyGroup<T>>(); foreach (CharacterGrouping cg in slg) { if (cg.Label == "") continue; else if (cg.Label == "...") { list.Add(new AlphaKeyGroup<T>(GlobeGroupKey)); } else list.Add(new AlphaKeyGroup<T>(cg.Label)); } return list; } public static List<AlphaKeyGroup<T>> CreateGroups(IEnumerable<T> items, Func<T, string> keySelector, bool sort) { CharacterGroupings slg = new CharacterGroupings(); List<AlphaKeyGroup<T>> list = CreateDefaultGroups(slg); foreach (T item in items) { int index = 0; string label = slg.Lookup(keySelector(item)); index = list.FindIndex(alphagroupkey => (alphagroupkey.Key.Equals(label, StringComparison.CurrentCulture))); if (index > -1 && index < list.Count) list[index].Add(item); } if (sort) { foreach (AlphaKeyGroup<T> group in list) { group.Sort((c0, c1) => { return keySelector(c0).CompareTo(keySelector(c1)); }); } } return list; } }
II. 添加可用于绑定到CollectionViewSource的List<AlphaKeyGroup<City>>属性,这里的City是自定义数据模型,如下:
//这里的代码是MVVM-Sidekick框架自动生成的,主要就是第一行的定义代码
public List<AlphaKeyGroup<City>> StartCityGroup { get { return _StartCityGroupLocator(this).Value; } set { _StartCityGroupLocator(this).SetValueAndTryNotify(value); } } #region Property List<AlphaKeyGroup<City>> StartCityGroup Setup protected Property<List<AlphaKeyGroup<City>>> _StartCityGroup = new Property<List<AlphaKeyGroup<City>>> { LocatorFunc = _StartCityGroupLocator }; static Func<BindableBase, ValueContainer<List<AlphaKeyGroup<City>>>> _StartCityGroupLocator = RegisterContainerLocator<List<AlphaKeyGroup<City>>>("StartCityGroup", model => model.Initialize("StartCityGroup", ref model._StartCityGroup, ref _StartCityGroupLocator, _StartCityGroupDefaultValueFactory)); static Func<BindableBase, List<AlphaKeyGroup<City>>> _StartCityGroupDefaultValueFactory = model => { var vm = CastToCurrentType(model); //TODO: Add the logic that produce default value from vm current status. return default(List<AlphaKeyGroup<City>>); }; #endregion
III. 给StartCityGrup赋予数据,这里就用到我们的辅助类了,实现如下:
//StartCity是List<City>类型的源数据集合 StartCityGroup = AlphaKeyGroup<City>.CreateGroups(StartCity, (City s) => { return s.Name; }, true);
这里因为我们要根据城市名称拼音分组,所以使用了对应的Name属性。
2.绑定视图
还需要设置ListView分组标头,设置GrupStyle,如下:
<ListView Margin="15,10" x:Name="StartCityList" ItemsSource="{Binding Source={StaticResource GroupData}}" Foreground="Black" Background="White" SelectionChanged="StartCityList_SelectionChanged" > <ListView.GroupStyle> <GroupStyle HidesIfEmpty="True"> <GroupStyle.HeaderTemplate> <DataTemplate> <Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62" Height="62" Margin="0,0,18,0" HorizontalAlignment="Stretch"> <TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6" FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/> </Border> </DataTemplate> </GroupStyle.HeaderTemplate> </GroupStyle> </ListView.GroupStyle> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Name}" FontSize="20"/> <TextBlock Margin="10,0,0,0" FontSize="20" Text="{Binding CityCode}"/> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView>
到了这里,ListView就可以实现拼音分组显示了。
IV.实现分组拼音跳转
这里就需要使用GridView和SemanticZoom控件,GridView控件用于显示拼音字母集合,SemanticZoom实现视图切换,实现代码如下:
<SemanticZoom Background="White" x:Name="semanticZoom" ViewChangeStarted="SemanticZoom_ViewChangeStarted"> <SemanticZoom.ZoomedInView> <ListView Margin="15,10" x:Name="StartCityList" ItemsSource="{Binding Source={StaticResource GroupData}}" Foreground="Black" Background="White" SelectionChanged="StartCityList_SelectionChanged" > <ListView.GroupStyle> <GroupStyle HidesIfEmpty="True"> <GroupStyle.HeaderTemplate> <DataTemplate> <Border Background="{StaticResource PhoneAccentBrush}" BorderBrush="{StaticResource PhoneAccentBrush}" BorderThickness="2" Width="62" Height="62" Margin="0,0,18,0" HorizontalAlignment="Stretch"> <TextBlock Text="{Binding Key}" Foreground="{StaticResource PhoneForegroundBrush}" FontSize="48" Padding="6" FontFamily="{StaticResource PhoneFontFamilySemiLight}" HorizontalAlignment="Left" VerticalAlignment="Center"/> </Border> </DataTemplate> </GroupStyle.HeaderTemplate> </GroupStyle> </ListView.GroupStyle> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Name}" FontSize="20"/> <TextBlock Margin="10,0,0,0" FontSize="20" Text="{Binding CityCode}"/> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> </SemanticZoom.ZoomedInView> <SemanticZoom.ZoomedOutView> <!-- 缩放后的跳转界面 --> <GridView x:Name="ZoomGridView" ItemsSource="{Binding View.CollectionGroups ,Source={StaticResource GroupData}}" HorizontalAlignment="Center" Background="Gray" VerticalAlignment="Center"> <GridView.ItemTemplate> <DataTemplate> <Border Background="White" > <Border Margin="2" Width="90" Height="90" HorizontalAlignment="Left" Background="{Binding Group.Count,Converter={StaticResource BackgroundConverter}}"> <TextBlock Text="{Binding Group.Key}" Foreground="White" FontSize="48" Padding="6" HorizontalAlignment="Left" VerticalAlignment="Center"/> </Border> </Border> </DataTemplate> </GridView.ItemTemplate> </GridView> </SemanticZoom.ZoomedOutView> </SemanticZoom>
这里需要注意一下,ListView和GridView使用同一个CollectionViewSource作为数据源时,可以实现自动分组跳转,不需要多余的代码。如果不是,则需要使用SemanticZoom控件的ViewChangeCompleted和ViewChangeStarted进行代码控制实现。
V. 实现分组标头颜色区分
这里我自定义了一个IValueConverter来进行GridView项显示颜色的转化,这里根据绑定分组数据的数量来区分,如果此分组有对应的数据则显示蓝色,如果分组数据为空,则显示为灰色,实际效果如第二张图片。
转换器实现代码:
class BackgroundConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if(value!=null)
{
var count = int.Parse(value.ToString());
if (count > 0)
return new SolidColorBrush(Windows.UI.Colors.Blue);
}
return new SolidColorBrush(Windows.UI.Colors.Gray);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
总结:
WinRT框架的实现拼音分组控件虽然复杂程度大增,但是其功能区的高度可自定义化,无疑是较大的进步,我想微软会在后续的更新中推出更好的控件或解决方案,希望这篇文章对于开发WinRT框架app的你有所帮助。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Windows Phone开发手记-WinRT下分组拼音的实现
- Windows Phone开发手记-WinRT下分组拼音的实现
- mybatis从数据库中取数据且分组,返回分组数据
- Java8中使用stream进行分组统计和普通实现的分组统计的性能对比
- LeetCode 手记 16
- PicaComic接口分析手记
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Rationality for Mortals
Gerd Gigerenzer / Oxford University Press, USA / 2008-05-02 / USD 65.00
Gerd Gigerenzer's influential work examines the rationality of individuals not from the perspective of logic or probability, but from the point of view of adaptation to the real world of human behavio......一起来看看 《Rationality for Mortals》 这本书的介绍吧!