在写一个看新闻软件的时候,用到了SemanticZoom控件,遇到了一些问题,比如如何根据首字母分类,以及放大视图中有数据的和没数据的通过背景色或前景色区分,幸运的是,all solved。
先来个效果图
主要是参考了msdn的一篇博客,地址已经放在参考链接里了。
首先是一个SemanticZoom控件,这个控件有ZoomedInView和ZoomedOutView两种视图。
ZoomedOutView视图就是这个
而ZoomedInView视图就是一个带有列表头的列表的样子,还是上个图好了,我个人不喜欢看一大段的纯文字
首先弄个Model,这里叫Picture
1 public class Picture2 {3 public string ImageUri { get; set; }4 public string Title { get; set; }5 }
然后再加个ViewModel,叫MainPageViewModel,类里写一个数据集合和加载数据的方法
1 public ObservableCollection<AlphaKeyGroup<Picture>> AllPictures { get; set; }
关于加载数据的方法,很显然,我们要把数据按照Title的首字母分组,按首字母分组说实话我不会,然后我在msdn找到了一个类叫AlphaKeyGroup,这个类可以用来按首字母分组

1 public class AlphaKeyGroup<T> : List<T> 2 { 3 /// <summary> 4 /// The delegate that is used to get the key information. 5 /// </summary> 6 /// <param name="item">An object of type T</param> 7 /// <returns>The key value to use for this object</returns> 8 public delegate string GetKeyDelegate(T item); 9 10 /// <summary>11 /// The Key of this group.12 /// </summary>13 public string Key { get; private set; }14 15 /// <summary>16 /// Public constructor.17 /// </summary>18 /// <param name="key">The key for this group.</param>19 public AlphaKeyGroup(string key)20 {21 Key = key;22 }23 24 /// <summary>25 /// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping.26 /// </summary>27 /// <param name="slg">The </param>28 /// <returns>Theitems source for a LongListSelector</returns>29 private static List<AlphaKeyGroup<T>> CreateGroups(SortedLocaleGrouping slg)30 {31 List<AlphaKeyGroup<T>> list = new List<AlphaKeyGroup<T>>();32 33 foreach (string key in slg.GroupDisplayNames)34 {35 list.Add(new AlphaKeyGroup<T>(key));36 }37 38 return list;39 }40 41 /// <summary>42 /// Create a list of AlphaGroup<T> with keys set by a SortedLocaleGrouping.43 /// </summary>44 /// <param name="items">The items to place in the groups.</param>45 /// <param name="ci">The CultureInfo to group and sort by.</param>46 /// <param name="getKey">A delegate to get the key from an item.</param>47 /// <param name="sort">Will sort the data if true.</param>48 /// <returns>An items source for a LongListSelector</returns>49 public static List<AlphaKeyGroup<T>> CreateGroups(IEnumerable<T> items, CultureInfo ci, GetKeyDelegate getKey, bool sort)50 {51 SortedLocaleGrouping slg = new SortedLocaleGrouping(ci);52 List<AlphaKeyGroup<T>> list = CreateGroups(slg);53 54 foreach (T item in items)55 {56 int index = 0;57 if (slg.SupportsPhonetics)58 {59 //check if your database has yomi string for item60 //if it does not, then do you want to generate Yomi or ask the user for this item.61 //index = slg.GetGroupIndex(getKey(Yomiof(item)));62 }63 else64 {65 index = slg.GetGroupIndex(getKey(item));66 }67 if (index >= 0 && index < list.Count)68 {69 list[index].Add(item);70 }71 }72 73 if (sort)74 {75 foreach (AlphaKeyGroup<T> group in list)76 {77 group.Sort((c0, c1) => { return ci.CompareInfo.Compare(getKey(c0), getKey(c1)); });78 }79 }80 81 return list;82 }83 84 }AlphaKeyGroup
使用的时候这样
1 //按拼音分组2 List<AlphaKeyGroup<Picture>> groupData = AlphaKeyGroup<Picture>.CreateGroups(3 picturesList, (Picture s) => s.Title, true);4 5 foreach (var item in groupData)6 {7 AllPictures.Add(item);8 }
当然首先要在Listpictures里加一些示例数据

1 picturesList.Add(new Picture { ImageUri = "http://t3.gstatic.com/images?q=tbn:ANd9GcQ_ih-aN2gxUz435mPC733IFDNhk1vqFQSVKshWMHEtzxKfKqbs", Title = "OOO" });2 picturesList.Add(new Picture { ImageUri = "http://4.bp.blogspot.com/-v4cAAv3ViZk/T3w0jsZocUI/AAAAAAAACE0/l21tSjKnSUI/s640/Cool_facebook_timeline_covers+%252814%2529.jpg", Title = "ZZZ" });3 picturesList.Add(new Picture { ImageUri = "http://t3.gstatic.com/images?q=tbn:ANd9GcTv1Kx5oic3I39RTIoAMrFOKQxaIKNtXSNSr5B5bUGsX5mRMMBl_Q", Title = "DDD" });4 picturesList.Add(new Picture { ImageUri = "http://t0.gstatic.com/images?q=tbn:ANd9GcRFzgy_qOhDZ3GAQVxIOi1oTg8VSToo8hX_0cxoD6ZqUW9K-r9p", Title = "BBB" });
然后开始写UI部分,当然要先把Page的DataContext设置到MainPageViewModel的实例,比较简单这里就不写了, 再在Xaml里加上一个CollectionViewSource,用来给SemanticZoom提供数据,ItemsPath填的是集合属性的名字,至于为什么填这个,看看AlphaKeyGroup类的源码就知道了,IsSourceGrouped意思是要把AllPictures分组
1 <CollectionViewSource x:Key="CollectionViewSource" IsSourceGrouped="True" 2 ItemsPath="InternalList"3 Source="{Binding AllPictures}"/>
开始写SemanticZoom

1 <SemanticZoom > 2 <SemanticZoom.Style> 3 <Style TargetType="SemanticZoom"> 4 <Setter Property="HorizontalContentAlignment" Value="Stretch"/> 5 </Style> 6 </SemanticZoom.Style> 7 <!--数据列表--> 8 <SemanticZoom.ZoomedInView> 9 <ListView ItemsSource="{Binding Source={StaticResource CollectionViewSource}}"10 SelectionMode="None" 11 ShowsScrollingPlaceholders="True"12 IsItemClickEnabled="True"13 ItemClick="ListView_ItemClick">14 <ListView.ItemTemplate>15 <DataTemplate>16 <Grid Padding="0,8"17 BorderThickness="{StaticResource BorderThickness}" 18 BorderBrush="{StaticResource BorderBrush}" >19 <Grid.ColumnDefinitions>20 <ColumnDefinition Width="2*"/>21 <ColumnDefinition Width="3*"/>22 <ColumnDefinition Width="Auto"/>23 </Grid.ColumnDefinitions>24 <Image Grid.Column="0" Stretch="Fill" HorizontalAlignment="Left" >25 <Image.Source>26 <BitmapImage UriSource="{Binding imageUri}"/>27 </Image.Source>28 </Image>29 <Grid Grid.Column="1" Margin="5,2">30 <TextBlock Text="{Binding Title}" VerticalAlignment="Top" TextWrapping="Wrap"/>31 </Grid>32 </Grid>33 </DataTemplate>34 </ListView.ItemTemplate>35 <ListView.ItemContainerStyle>36 <Style TargetType="ListViewItem">37 <Setter Property="HorizontalContentAlignment" Value="Stretch"/>38 <Setter Property="Margin" Value="0"/>39 </Style>40 </ListView.ItemContainerStyle>41 <!--列表头-->42 <ListView.GroupStyle>43 <GroupStyle HidesIfEmpty="True" >44 <GroupStyle.HeaderTemplate>45 <DataTemplate>46 <TextBlock Text="{Binding Key}" FontSize="25" Foreground="Red"/>47 </DataTemplate>48 </GroupStyle.HeaderTemplate>49 </GroupStyle>50 </ListView.GroupStyle>51 </ListView>52 </SemanticZoom.ZoomedInView>53 <!--排序列表-->54 <SemanticZoom.ZoomedOutView>55 <GridView ItemsSource="{Binding Source={StaticResource CollectionViewSource},Path=CollectionGroups}">56 <GridView.ItemsPanel>57 <ItemsPanelTemplate>58 <WrapGrid MaximumRowsOrColumns="4" VerticalAlignment="Top" Orientation="Horizontal"/>59 </ItemsPanelTemplate>60 </GridView.ItemsPanel>61 <GridView.ItemTemplate>62 <DataTemplate>63 <Border Background="{Binding Converter={StaticResource BackgroundConverter}}">64 <TextBlock Text="{Binding Group.Key}" HorizontalAlignment="Center" 65 VerticalAlignment="Center"66 Foreground="{Binding Converter={StaticResource ForegroundConverter}}"/>67 </Border>68 </DataTemplate>69 </GridView.ItemTemplate>70 71 <GridView.ItemContainerStyle>72 <Style TargetType="GridViewItem">73 <Setter Property="HorizontalAlignment" Value="Center"/>74 <Setter Property="HorizontalContentAlignment" Value="Stretch"/>75 <Setter Property="VerticalAlignment" Value="Center"/>76 <Setter Property="VerticalContentAlignment" Value="Stretch"/>77 </Style>78 </GridView.ItemContainerStyle>79 <GridView.Template>80 <ControlTemplate>81 <ScrollViewer ScrollViewer.VerticalScrollMode="Enabled">82 <Viewbox Stretch="Uniform" Margin="8" VerticalAlignment="Top" 83 ScrollViewer.VerticalScrollMode="Enabled" StretchDirection="Both" >84 <ItemsPresenter />85 </Viewbox>86 </ScrollViewer>87 </ControlTemplate>88 </GridView.Template>89 </GridView>90 </SemanticZoom.ZoomedOutView>91 </SemanticZoom>SemanticZoom
注意到排序列表的GridView.ItemTemplate ,用到了两个Converter,即BackgroundConverter和ForegroundConverter
1 <Border Background="{Binding Converter={StaticResource BackgroundConverter}}">2 <TextBlock Text="{Binding Group.Key}" HorizontalAlignment="Center" 3 VerticalAlignment="Center"4 Foreground="{Binding Converter={StaticResource ForegroundConverter}}"/>5 </Border>
我一直想实现在ZoomedOutView里那种有数据的和没数据的用颜色区分的功能,自己写Converter没写出来,然后发现了这个
这两个Converter是系统自带的,用的时候设置好Enabled和Disabled的颜色,有数据的时候显示Enabled的颜色,没有就显示Disabled的颜色
1 <JumpListItemBackgroundConverter x:Key="BackgroundConverter" Enabled="Red"2 Disabled="Transparent"/>3 <JumpListItemBackgroundConverter x:Key="ForegroundConverter" Enabled="White" Disabled="Black"/>
其他没什么了,附上demo
SemanticZoomDemo
参考链接
http://blogs.msdn.com/b/msgulfcommunity/archive/2013/06/18/implementing-longlistselector-as-jumplists-in-windows-phone-8-alphabetical-list.aspx
- 热点聚合:控件 SemanticZoom 使用 UWP