Windows Phone 7 LongListSelector控件实现分类列表和字母索引
在wp7手机里面的联系人列表和程序里面里面我们可以看到一个根据字母索引来定位联系人或者应用程序的控件,那么这个控件就是longlistselector控件了。
longlistselector是一种比listbox更加强大的列表控件,你可以根据你列表的信息来分类排列,根据类别快速定位到你选中的类别的列表下,在数据量很大的情况下这种分类的优势很明显。longlistselector可以自定义列表头,列表尾、类表头、列别尾等的样式和数据,可以实现各种个性化的列表样式和不同的数据的展现方式。windows phone 7手机的联系人列表就是基于longlistselector控件设计的。longlistselector控件的常用属性和常用事件分别如表12.6和表12.7所示。
表12.6 longlistselector控件常用属性
名称 | 说明 |
displayallgroups | bool类型的属性,当值为true时,它显示所有的分组无论该组中是否有选项或者数据,默认值为false。 |
groupfootertemplate | datatemplate类型的属性,它是负责绑定每个组的底部的数据和样式的模板。 |
groupheadertemplate | datatemplate类型的属性,它是负责绑定每个组的顶部的数据和样式的模板。 |
groupitemspanel | itemspaneltemplate类型的属性,设置组的内部的panel面板的内容。 |
groupitemtemplate | datatemplate类型的属性,它是负责绑定每个组里面的元素的数据和样式的模板。 |
itemtemplate | datatemplate类型的属性,它是负责绑定所有选项或者元素的数据和样式的模板。 |
listfootertemplate | datatemplate类型的属性,它是负责绑定整个list底部的数据和样式的模板。 |
listheadertemplate | datatemplate类型的属性,它是负责绑定整个list顶部的数据和样式的模板。 |
selecteditem | 获取或者设置选中的选项 |
showlistfooter | bool类型的属性,是否显示列脚,默认值为true。 |
showlistheader | bool类型的属性,是否显示列头,默认值为true。 |
表12.7 longlistselector控件常用事件
名称 | 说明 |
link | 当查找的内容被找到时,触发的事件。 用法示例: selector.link += new eventhandler<linkunlinkeventargs>(selector_link); void selector_link(object sender, linkunlinkeventargs e) {...} |
unlink | 查找的内容没有被找到时,触发的事件。 用法示例: selector.unlink += new eventhandler<linkunlinkeventargs>(selector_unlink); void selector_unlink(object sender, linkunlinkeventargs e) {... } |
selectionchanged | 选择的选项改变时触发的事件。 用法示例: selector.selectionchanged += new selectionchangedeventhandler(selector_selectionchanged); void selector_selectionchanged(object sender, selectionchangedeventargs e) {... } |
scrollingcompleted | 当列表滚动结束的时候触发的事件。 用法示例: selector.scrollingcompleted += new eventhandler(selector_scrollingcompleted); void selector_scrollingcompleted(object sender, eventargs e) {...} |
scrollingstarted | 当列表滚动开始的时候触发的事件。 用法示例: selector.scrollingstarted += new eventhandler(selector_scrollingstarted); void selector_scrollingstarted(object sender, eventargs e){...} |
代码清单12-6:列表选择框(源代码:第12章\examples_12_6)
mainpage.xaml文件主要代码
<phone:phoneapplicationpage.resources>
<!—定义组头绑定模板-->
<datatemplate x:key="groupheader">
<border background="{staticresource phoneaccentbrush}" margin="{staticresource phonetouchtargetoverhang}" padding="{staticresource phonetouchtargetoverhang}">
<textblock text="{binding key}"/>
</border>
</datatemplate>
<!—定义组选项绑定模板-->
<datatemplate x:key="groupitem">
<border background="{staticresource phoneaccentbrush}" margin="{staticresource phonetouchtargetoverhang}" padding="{staticresource phonetouchtargetoverhang}">
<textblock text="{binding key}" style="{staticresource phonetextlargestyle}"/>
</border>
</datatemplate>
<!—定义列头绑定模板-->
<datatemplate x:key="listheader">
<textblock text="header" style="{staticresource phonetexttitle1style}"/>
</datatemplate>
<!—定义列表选项绑定模板-->
<datatemplate x:key="itemtmpl">
<grid>
<textblock text="{binding title}"></textblock>
</grid>
</datatemplate>
</phone:phoneapplicationpage.resources>
……
<!--添加longlistselector控件-->
<grid x:name="contentpanel" grid.row="1" margin="12,0,12,0">
<toolkit:longlistselector x:name="longlist" background="transparent"
itemtemplate="{staticresource itemtmpl}"
listheadertemplate="{staticresource listheader}"
groupheadertemplate="{staticresource groupheader}"
groupitemtemplate="{staticresource groupitem}" >
</toolkit:longlistselector>
</grid>
</grid>
</phone:phoneapplicationpage>
mainpage.xaml.cs文件代码
using system;
using system.collections.generic;
using system.linq;
using system.windows;
using system.windows.controls;
using microsoft.phone.controls;
namespace longlistselectordemo
{
public partial class mainpage : phoneapplicationpage
{
public mainpage()
{
initializecomponent();
//使用list<t>来初始化数据
list<item> mainitem = new list<item>();
for (int i = 0; i < 10; i++)
{
mainitem.add(new item() { content = "a类别", title = "测试a " + i.tostring() });
mainitem.add(new item() { content = "b类别", title = "测试b" + i.tostring() });
mainitem.add(new item() { content = "c类别", title = "测试c" + i.tostring() });
}
//使用linq来查询list<item>数据 按照content来进行分组
var selected = from c in mainitem group c by c.content into n select new groupinglayer<string, item>(n);
this.longlist.itemssource = selected;
}
//继承linq的igrouping接口 来存储分组的数据
public class groupinglayer<tkey, telement> : igrouping<tkey, telement>
{
//分组数据
private readonly igrouping<tkey, telement> grouping;
//初始化
public groupinglayer(igrouping<tkey, telement> unit)
{
grouping = unit;
}
//唯一的键值
public tkey key
{
get { return grouping.key; }
}
//重载判断相等方法
public override bool equals(object obj)
{
groupinglayer<tkey, telement> that = obj as groupinglayer<tkey, telement>;
return (that != null) && (this.key.equals(that.key));
}
public ienumerator<telement> getenumerator()
{
return grouping.getenumerator();
}
system.collections.ienumerator system.collections.ienumerable.getenumerator()
{
return grouping.getenumerator();
}
}
//list选项的类 content表示类别 title表示选项的标题
public class item
{
public string title { get; set; }
public string content { get; set; }
}
}
}
下面再来看看第二例子,实现longlistselector控件的字母索引。
item.cs
namespace longlistselectordemo
{
/// <summary>
/// 选项实体类
/// </summary>
public class item
{
public string name { get; set; }
public string content { get; set; }
//获取名字的首个字符用来作为分组的依据
public static string getfirstnamekey(item item)
{
char key;
key = char.tolower(item.name[0]);
if (key < 'a' || key > 'z')
{
key = '#';
}
return key.tostring();
}
}
}
itemingroup.cs
using system.collections.generic;
namespace longlistselectordemo
{
/// <summary>
/// 组集合
/// </summary>
public class itemingroup: list<item>
{
public itemingroup(string category)
{
key = category;
}
//组的键
public string key { get; set; }
//组是否有选项
public bool hasitems { get { return count > 0; } }
}
}
items.cs
using system.collections.generic;
namespace longlistselectordemo
{
/// <summary>
/// 总数据集合
/// </summary>
public class items: list<itemingroup>
{
//索引
private static readonly string groups = "#|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z";
public items()
{
//获取要绑定的数据源
list<item> items = new list<item>();
items.add(new item { name = "a测试", content = "a内容" });
items.add(new item { name = "b测试", content = "b内容" });
items.add(new item { name = "c测试", content = "c内容" });
items.add(new item { name = "d测试", content = "d内容" });
items.add(new item { name = "e测试", content = "e内容" });
items.add(new item { name = "f测试", content = "f内容" });
items.add(new item { name = "g测试", content = "g内容" });
//组的字典列表
dictionary<string, itemingroup> groups = new dictionary<string, itemingroup>();
//初始化组列表,即用字母列表来分组
foreach (string c in groups.split('|'))
{
itemingroup group = new itemingroup(c.tostring());
//添加组数据到集合
this.add(group);
groups[c.tostring()] = group;
}
//初始化选项列表,即按照选项所属的组来放进它属于的组里面
foreach (item item in items)
{
//添加选项数据到集合
groups[item.getfirstnamekey(item)].add(item);
}
}
}
}
mainpage.xaml
<grid x:name="contentpanel" grid.row="1" margin="12,0,12,0">
<toolkit:longlistselector x:name="longlistselector" background="transparent"
margin="0,-8,0,0">
<toolkit:longlistselector.groupitemspanel>
<itemspaneltemplate>
<toolkit:wrappanel orientation="horizontal"/>
</itemspaneltemplate>
</toolkit:longlistselector.groupitemspanel>
<toolkit:longlistselector.groupitemtemplate>
<datatemplate>
<border background="red"
width="99" height="99" margin="6" ishittestvisible="{binding hasitems}">
<textblock text="{binding key}"
fontfamily="{staticresource phonefontfamilysemibold}"
fontsize="48"
margin="8,0,0,0"
foreground="white"
verticalalignment="bottom"/>
</border>
</datatemplate>
</toolkit:longlistselector.groupitemtemplate>
<toolkit:longlistselector.groupheadertemplate>
<datatemplate>
<border background="transparent" margin="12,8,0,8">
<border background="{staticresource phoneaccentbrush}"
padding="8,0,0,0" width="62" height="62"
horizontalalignment="left">
<textblock text="{binding key}"
foreground="#ffffff"
fontsize="48"
fontfamily="{staticresource phonefontfamilysemilight}"
horizontalalignment="left"
verticalalignment="bottom"/>
</border>
</border>
</datatemplate>
</toolkit:longlistselector.groupheadertemplate>
<toolkit:longlistselector.itemtemplate>
<datatemplate>
<grid margin="12,8,0,8">
<grid.columndefinitions>
<columndefinition width="auto"/>
<columndefinition width="*"/>
</grid.columndefinitions>
<stackpanel grid.column="1" verticalalignment="top">
<textblock text="{binding name}" style="{staticresource phonetextlargestyle}" fontfamily="{staticresource phonefontfamilysemibold}" margin="12,-12,12,6"/>
<textblock text="{binding content}" style="{staticresource phonetextnormalstyle}" textwrapping="wrap" fontfamily="{staticresource phonefontfamilysemibold}"/>
</stackpanel>
</grid>
</datatemplate>
</toolkit:longlistselector.itemtemplate>
</toolkit:longlistselector>
</grid>
mainpage.xaml.cs
using microsoft.phone.controls;
namespace longlistselectordemo
{
public partial class mainpage : phoneapplicationpage
{
// constructor
public mainpage()
{
initializecomponent();
longlistselector.itemssource = new items();
}
}
}
运行的效果如下:
摘自 linzheng