欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

[UWP] 使用SemanticZoom控件

程序员文章站 2022-03-08 16:03:30
在写一个看新闻软件的时候,用到了SemanticZoom控件,遇到了一些问题,比如如何根据首字母分类,以及放大视图中有数据的和没数据的通过背景色或前景色区分,幸运的是,all solved。 先来个效果图 主要是参考了msdn的一篇博客,地址已经放在参考链接里了。 首先是一个SemanticZoom ......

在写一个看新闻软件的时候,用到了SemanticZoom控件,遇到了一些问题,比如如何根据首字母分类,以及放大视图中有数据的和没数据的通过背景色或前景色区分,幸运的是,all solved。

先来个效果图

[UWP] 使用SemanticZoom控件

 主要是参考了msdn的一篇博客,地址已经放在参考链接里了。

首先是一个SemanticZoom控件,这个控件有ZoomedInView和ZoomedOutView两种视图。

ZoomedOutView视图就是这个

[UWP] 使用SemanticZoom控件

 而ZoomedInView视图就是一个带有列表头的列表的样子,还是上个图好了,我个人不喜欢看一大段的纯文字

[UWP] 使用SemanticZoom控件

 

首先弄个Model,这里叫Picture

1  public class Picture
2     {
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,这个类可以用来按首字母分组

[UWP] 使用SemanticZoom控件
 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 item
60                     //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                 else
64                 {
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

使用的时候这样,CreateGroups方法有三个参数,第一个是要分组的数据,第二个参数是分组的方法,第三个参数是是否排序,该方法返回了一个List<AlphaKeyGroup<Picture>>类型的数据,

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  }

当然首先要在picturesList里加一些示例数据

[UWP] 使用SemanticZoom控件
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" });
View Code

然后开始写UI部分,当然要先把Page的DataContext设置到MainPageViewModel的实例,比较简单这里就不写了, 再在Xaml里加上一个CollectionViewSource,用来给SemanticZoom提供数据,ItemsPath填的是集合属性的名字,至于为什么填这个,看看AlphaKeyGroup类的源码就知道了,里面有个List<T>类型的 InternalList,数据就是被存在这里的,IsSourceGrouped意思是要把AllPictures分组

1 <CollectionViewSource x:Key="CollectionViewSource" IsSourceGrouped="True" 
2                                           ItemsPath="InternalList"
3                                           Source="{Binding AllPictures}"/>

开始写SemanticZoom

[UWP] 使用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

 还有一个待解决的问题,在ZoomOutView中如何将无数据的项变成不可点击状态?既然那两个Converter能知道哪个是没数据的,说明一定有办法,Pending……

参考链接

http://blogs.msdn.com/b/msgulfcommunity/archive/2013/06/18/implementing-longlistselector-as-jumplists-in-windows-phone-8-alphabetical-list.aspx