在寫一個看新聞軟體的時候,用到了SemanticZoom控制項,遇到了一些問題,比如如何根據首字母分類,以及放大視圖中有數據的和沒數據的通過背景色或前景色區分,幸運的是,all solved。 先來個效果圖 主要是參考了msdn的一篇博客,地址已經放在參考鏈接里了。 首先是一個SemanticZoom
在寫一個看新聞軟體的時候,用到了SemanticZoom控制項,遇到了一些問題,比如如何根據首字母分類,以及放大視圖中有數據的和沒數據的通過背景色或前景色區分,幸運的是,all solved。
先來個效果圖
主要是參考了msdn的一篇博客,地址已經放在參考鏈接里了。
首先是一個SemanticZoom控制項,這個控制項有ZoomedInView和ZoomedOutView兩種視圖。
ZoomedOutView視圖就是這個
而ZoomedInView視圖就是一個帶有列表頭的列表的樣子,還是上個圖好了,我個人不喜歡看一大段的純文字
首先弄個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,這個類可以用來按首字母分組
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
使用的時候這樣
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裡加一些示例數據
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類的源碼就知道了,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
參考鏈接