Windows Phone开发手记-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 = ;
string label = slg.Lookup(keySelector(item));
index = list.FindIndex(alphagroupkey => (alphagroupkey.Key.Equals(label, StringComparison.CurrentCulture)));
if (index > - && 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下自定义圆形ItemsControl
这里的ItemsControl指的是Xaml里的集合控件,包括ListView,GridView等,此篇博客主要参考MSDN Blog的一篇文章,具体出处为:http://blogs.msdn.com ...
- Windows Phone开发手记-WinRT下启动器替代方案
在WP7/8时代,Silverlight框架提供了很多启动器API,我们可以很方便的使用的,来完成一些系统级的操作.但是随着Win RT架构的WP8.1(SL 8.1除外)的到来,原有的SL下的启动器 ...
- Android开发手记(10) 下拉菜单Spinner
1.自定义Spinner 首先,定义Spinner要显示的项目列表/res/values/arrays.xml <?xml version="1.0" encoding=&q ...
- Windows Phone开发(11):常用控件(下)
原文:Windows Phone开发(11):常用控件(下) WP控件大部分都可以从Silverlight中继承过来,这里我也只能拿一部分作演示,对于其它控件如何使用,可以参考SDK相关说明以及Sil ...
- windows RT开发笔记:WinRT DLL及其调用研究
一. 几个概念: WinRT : Windows Runtime, windows运行时.创建Windows运行时(WinRT)是为了在Windows上给用户提供一种流畅且安全的应用体验.WinRT会 ...
- Kinect for Windows SDK开发入门(15):进阶指引 下
Kinect for Windows SDK开发入门(十五):进阶指引 下 上一篇文章介绍了Kinect for Windows SDK进阶开发需要了解的一些内容,包括影像处理Coding4Fun K ...
- 【VS开发】【miscellaneous】windows(64位)下使用curl命令
windows(64位)下使用curl命令 Curl命令可以通过命令行的方式,执行Http请求.在Elasticsearch中有使用的场景,因此这里研究下如何在windows下执行curl命令. 工具 ...
- Windows 10 开发人员预览版中的新增功能(转自 IT之家)
Windows 10 开发人员预览版中的新增功能 在Win10预览版中安装工具与SDK后,即可着手创建Windows通用应用或先浏览目前的环境与此前相比都发生了什么变化. 应用建模 文件资源管理器: ...
- HoloLens开发手记 - Unity development overview 使用Unity开发概述
Unity Technical Preview for HoloLens最新发行版为:Beta 24,发布于 09/07/2016 开始使用Unity开发HoloLens应用之前,确保你已经安装好了必 ...
随机推荐
- 02.制作一个自己的 Java 编辑器
难度中等,适合 Java 基础扎实,对 Java 核心 API 有所熟悉的同学学习 No1.制作GUI界面 一.实验介绍 1.1 实验内容 本节课程的主要内容是准备开发环境,建立项目并完成 GUI 界 ...
- Java HttpURLConnection 下载图片 图片全是“加密图片”文字,怎么解决?
package com.qzf.util; import java.io.FileOutputStream;import java.io.IOException;import java.io.Inpu ...
- Codeforces Round #544 (Div. 3) dp + 双指针
https://codeforces.com/contest/1133/problem/E 题意 给你n个数(n<=5000),你需要对其挑选并进行分组,总组数不能超过k(k<=5000) ...
- IntelliJ IDEA 2017版 编译器使用学习笔记(八) (图文详尽版);IDE快捷键使用;IDE代码重构(寻找修改痕迹)
git集成: 快速找到版本控制器中某段代码的作者 一.annotate 选中某行代码,右键,选择annotate,鼠标放于其上就会显示注释 二.移动所有改动之处: prev ...
- IntelliJ IDEA 2017版 spring-boot2.0.2 自动配置Condition
描述: 编译器修改参数 -Dfile.encoding=GBK -Dstr.encoding=GBK Condition位置: 某一个类或注解存在的时候,装配,否则不装配 相关代码: ...
- Windows 下 Quartus 检测不到 USB-Blaster 终极解决办法
转自https://blog.csdn.net/acang301/article/details/50471067?locationNum=12 一.Windows无法正常驱动USB-Blaster ...
- Grand Central Dispatch
什么是GCD? Grand Central Dispatch或者GCD,是一套低层API,提供了一种新的方法来进行并发程序编写.从基本功能上讲,GCD有点像NSOperationQueue,他们都允许 ...
- OpenGL中的拾取模式( Picking)
1. Opengl中的渲染模式有三种:(1)渲染模式,默认的模式:(2)选择模式, (3)反馈模式.如下 GLint glRenderMode(GLenum mode) mode可以选取以下三种模式之 ...
- Hive为什么要分桶
对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分.Hive也是针对某一列进行桶的组织.Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记 ...
- iOS处理视图上同时添加单击与双击手势的冲突问题
_bgView.userInteractionEnabled = YES; //在cell上添加 bgView,给bgView添加两个手势检测方法 UITapGestureRecognizer *do ...