Let me brief you about Semantic Zoom control.
  • The semantic zoom control enables the user to zoom between the two different views of the same content.
  • It has zoomed in and zoomed out components.
  • The zoomed in view is the main ListView, which the user will be first presented with.
  • The zoomed out view is the higher level view of the same content.
Here in this article, to make it simple, I haven't used MVVM Pattern.
Add the classes, given below, "JumpListHelper" and "JumpListGroup", which helps to group the data properly. It groups the items into the alphabetical groups and sorts the items.
  1. public class JumpListGroup<T> : List<object>
  2. {
  3. public object Key { get; set; }
  4. public new IEnumerator<object> GetEnumerator()
  5. {
  6. return (System.Collections.Generic.IEnumerator<object>)base.GetEnumerator();
  7. }
  8. }
  9. public static class JumpListHelper
  10. {
  11. public static List<JumpListGroup<TSource>> ToAlphaGroups<TSource>(
  12. this IEnumerable<TSource> source, Func<TSource, string> selector)
  13. {
  14. var characterGroupings = new CharacterGroupings();
  15. var keys = characterGroupings.Where(x => x.Label.Any())
  16. .Select(x => x.Label)
  17. .ToDictionary(x => x);
  18. keys["..."] = "\uD83C\uDF10";
  19. var groupDictionary = keys.Select(x => new JumpListGroup<TSource>() { Key = x.Value })
  20. .ToDictionary(x => (string)x.Key);
  21. var query = from item in source
  22. orderby selector(item)
  23. select item;
  24. foreach (var item in query)
  25. {
  26. var sortValue = selector(item);
  27. groupDictionary[keys[characterGroupings.Lookup(sortValue)]].Add(item);
  28. }
  29. return groupDictionary.Select(x => x.Value).ToList();
  30. }
  31. }
Once, the data is grouped, we need to bind the data to our UI control. CollectionViewSource class helps to bind the grouped data. Add the code, given below:
  1. public class CountryJumplist
  2. {
  3. private ObservableCollection<Country> loadedCountry = new ObservableCollection<Country>();
  4. public CountryJumplist(object country)
  5. {
  6. this.loadedCountry = country as ObservableCollection<Country>;
  7. }
  8. private IList data;
  9. public IList Data
  10. {
  11. get
  12. {
  13. if (this.data == null)
  14. {
  15. var items = this.loadedCountry;
  16. this.data = items.ToAlphaGroups(x => x.CountryName);
  17. }
  18. return this.data;
  19. }
  20. }
  21. private CollectionViewSource collection;
  22. public CollectionViewSource Collection
  23. {
  24. get
  25. {
  26. if (this.collection == null)
  27. {
  28. this.collection = new CollectionViewSource();
  29. this.collection.Source = this.Data;
  30. this.collection.IsSourceGrouped = true;
  31. }
  32. return this.collection;
  33. }
  34. }
  35. }
  36. public class Country
  37. {
  38. public string CountryName { get; set; }
  39. }
XAML Page
Add the code, given below, in your XAML page.
  1. <Page.Resources>
  2. <JumpListItemBackgroundConverter x:Key="JumpListItemBackgroundConverter" />
  3. <JumpListItemForegroundConverter x:Key="JumpListItemForegroundConverter" />
  4. <!--DATA TEMPLATES-->
  5. <DataTemplate x:Key="AlphaGroupHeaderTemplate">
  6. <TextBlock Text="{Binding Key}"
  7. Foreground="{ThemeResource SystemControlBackgroundAccentBrush}"
  8. FontSize="32"
  9. FontFamily="{StaticResource PhoneFontFamilySemiLight}"
  10. FontWeight="Medium"
  11. HorizontalAlignment="Left"
  12. VerticalAlignment="Bottom"
  13. Margin="5.5,0,0,9.5" />
  14. </DataTemplate>
  15. <DataTemplate x:Key="AlphaJumpListPickerItemTemplate">
  16. <Border Background ="Transparent"
  17. BorderThickness="0"
  18. Height="60"
  19. Width="60"
  20. HorizontalAlignment="Center"
  21. Margin="0,0,1.5,1.5">
  22. <TextBlock Text="{Binding Group.Key}"
  23. Foreground="{Binding Converter={StaticResource JumpListItemBackgroundConverter}}"
  24. FontSize="22"
  25. FontWeight="SemiBold"
  26. HorizontalAlignment="Center"
  27. VerticalAlignment="Center"
  28. Margin="1.5,0,0,1.5" />
  29. </Border>
  30. </DataTemplate>
  31. <!--Remove header seperator line in listView groupStyle -->
  32. <Style TargetType="ListViewHeaderItem">
  33. <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
  34. <Setter Property="FontSize" Value="{ThemeResource ListViewHeaderItemThemeFontSize}" />
  35. <Setter Property="Background" Value="Transparent" />
  36. <Setter Property="Margin" Value="0,0,0,0"/>
  37. <Setter Property="Padding" Value="6,8,12,0"/>
  38. <Setter Property="HorizontalContentAlignment" Value="Left" />
  39. <Setter Property="VerticalContentAlignment" Value="Bottom" />
  40. <Setter Property="MinHeight" Value="{ThemeResource ListViewHeaderItemMinHeight}"/>
  41. <Setter Property="UseSystemFocusVisuals" Value="True" />
  42. <Setter Property="Template">
  43. <Setter.Value>
  44. <ControlTemplate TargetType="ListViewHeaderItem">
  45. <StackPanel Background="{TemplateBinding Background}"
  46. BorderBrush="{TemplateBinding BorderBrush}"
  47. BorderThickness="{TemplateBinding BorderThickness}">
  48. <ContentPresenter x:Name="ContentPresenter"
  49. Margin="{TemplateBinding Padding}"
  50. Content="{TemplateBinding Content}"
  51. ContentTemplate="{TemplateBinding ContentTemplate}"
  52. ContentTransitions="{TemplateBinding ContentTransitions}"
  53. HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
  54. VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
  55. </StackPanel>
  56. </ControlTemplate>
  57. </Setter.Value>
  58. </Setter>
  59. </Style>
  60. </Page.Resources>
  61. <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  62. <SemanticZoom HorizontalContentAlignment="Stretch"
  63. HorizontalAlignment="Stretch">
  64. <SemanticZoom.ZoomedInView>
  65. <ListView x:Name="lstAlphaGroupHeader"
  66. ItemsSource="{Binding CountryCollectionView}"
  67. SelectionMode="Single"
  68. HorizontalContentAlignment="Stretch">
  69. <ListView.GroupStyle>
  70. <GroupStyle HeaderTemplate="{StaticResource AlphaGroupHeaderTemplate}"
  71. HidesIfEmpty="True" />
  72. </ListView.GroupStyle>
  73. <ListView.ItemTemplate>
  74. <DataTemplate>
  75. <TextBlock Text="{Binding CountryName}"/>
  76. </DataTemplate>
  77. </ListView.ItemTemplate>
  78. </ListView>
  79. </SemanticZoom.ZoomedInView>
  80. <SemanticZoom.ZoomedOutView>
  81. <GridView x:Name="grdAlphaJumpListPicker"
  82. ItemsSource="{Binding CountryCollectionViewCollectionGroups}"
  83. HorizontalAlignment="Center"
  84. HorizontalContentAlignment="Stretch"
  85. VerticalAlignment="Center"
  86. ItemTemplate="{StaticResource AlphaJumpListPickerItemTemplate}">
  87. </GridView>
  88. </SemanticZoom.ZoomedOutView>
  89. </SemanticZoom>
  90. </Grid>
Listview and Gridview have been used inside Semantic zoom control for zoom in and zoom out views. In page resources, I added a couple of DataTemplates ("AlphaGroupHeaderTemplate" and "AlphaJumpListPickerItemTemplate") to design and bind for zoom in and zoom out views.
Cs Page
Add the code, given below, in cs page.
  1. protected override void OnNavigatedTo(NavigationEventArgs e)
  2. {
  3. base.OnNavigatedTo(e);
  4. LoadJumpList();
  5. }
  6. public void LoadJumpList()
  7. {
  8. ObservableCollection<Country> CountryList = new ObservableCollection<Country>();
  9. CountryList.Add(new Country() { CountryName = "Afghanistan" });
  10. CountryList.Add(new Country() { CountryName = "Australia" });
  11. CountryList.Add(new Country() { CountryName = "Austria" });
  12. CountryList.Add(new Country() { CountryName = "Bahrain" });
  13. CountryList.Add(new Country() { CountryName = "Bangladesh" });
  14. CountryList.Add(new Country() { CountryName = "Belgium" });
  15. CountryList.Add(new Country() { CountryName = "Brazil" });
  16. CountryList.Add(new Country() { CountryName = "Canada" });
  17. CountryList.Add(new Country() { CountryName = "Costa Rica" });
  18. CountryList.Add(new Country() { CountryName = "Denmark" });
  19. CountryList.Add(new Country() { CountryName = "Egypt" });
  20. CountryList.Add(new Country() { CountryName = "Ethiopia" });
  21. CountryList.Add(new Country() { CountryName = "Finland" });
  22. CountryList.Add(new Country() { CountryName = "France" });
  23. CountryList.Add(new Country() { CountryName = "Germany" });
  24. CountryList.Add(new Country() { CountryName = "Greece" });
  25. CountryList.Add(new Country() { CountryName = "Hungary" });
  26. CountryList.Add(new Country() { CountryName = "Iceland" });
  27. CountryList.Add(new Country() { CountryName = "India" });
  28. CountryList.Add(new Country() { CountryName = "Ireland" });
  29. CountryList.Add(new Country() { CountryName = "Italy" });
  30. CountryList.Add(new Country() { CountryName = "Japan" });
  31. CountryList.Add(new Country() { CountryName = "Kenya" });
  32. CountryList.Add(new Country() { CountryName = "Luxembourg" });
  33. CountryList.Add(new Country() { CountryName = "Malaysia" });
  34. CountryList.Add(new Country() { CountryName = "Netherlands" });
  35. CountryList.Add(new Country() { CountryName = "New Zealand" });
  36. CountryList.Add(new Country() { CountryName = "Oman" });
  37. CountryList.Add(new Country() { CountryName = "Pakistan" });
  38. CountryList.Add(new Country() { CountryName = "Qatar" });
  39. CountryList.Add(new Country() { CountryName = "Russia" });
  40. CountryList.Add(new Country() { CountryName = "Singapore" });
  41. CountryList.Add(new Country() { CountryName = "South Africa" });
  42. CountryList.Add(new Country() { CountryName = "Thailand" });
  43. CountryList.Add(new Country() { CountryName = "United Kingdom (UK)" });
  44. CountryList.Add(new Country() { CountryName = "United States of America (USA)" });
  45. CountryList.Add(new Country() { CountryName = "Vietnam" });
  46. CountryList.Add(new Country() { CountryName = "Yemen" });
  47. CountryList.Add(new Country() { CountryName = "Zimbabwe" });
  48. CountryJumplist countryJumpList = new CountryJumplist(CountryList);
  49. lstAlphaGroupHeader.ItemsSource = countryJumpList.Collection.View;
  50. grdAlphaJumpListPicker.ItemsSource = countryJumpList.Collection.View.CollectionGroups;
  51. }
I have added the items to object "CountryList" of type ObservableCollection<Country>, then I am passing the object as a constructor paramater of CountryJumpList.
Your MainPage.cs page looks like:
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Collections.ObjectModel;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Runtime.InteropServices.WindowsRuntime;
  8. using Windows.Foundation;
  9. using Windows.Foundation.Collections;
  10. using Windows.Globalization.Collation;
  11. using Windows.UI.Xaml;
  12. using Windows.UI.Xaml.Controls;
  13. using Windows.UI.Xaml.Controls.Primitives;
  14. using Windows.UI.Xaml.Data;
  15. using Windows.UI.Xaml.Input;
  16. using Windows.UI.Xaml.Media;
  17. using Windows.UI.Xaml.Navigation;
  18. namespace SemanticZoomSample
  19. {
  20. public sealed partial class MainPage : Page
  21. {
  22. public MainPage()
  23. {
  24. this.InitializeComponent();
  25. }
  26. protected override void OnNavigatedTo(NavigationEventArgs e)
  27. {
  28. base.OnNavigatedTo(e);
  29. LoadJumpList();
  30. }
  31. public void LoadJumpList()
  32. {
  33. ObservableCollection<Country> CountryList = new ObservableCollection<Country>();
  34. CountryList.Add(new Country() { CountryName = "Afghanistan" });
  35. CountryList.Add(new Country() { CountryName = "Australia" });
  36. CountryList.Add(new Country() { CountryName = "Austria" });
  37. CountryList.Add(new Country() { CountryName = "Bahrain" });
  38. CountryList.Add(new Country() { CountryName = "Bangladesh" });
  39. CountryList.Add(new Country() { CountryName = "Belgium" });
  40. CountryList.Add(new Country() { CountryName = "Brazil" });
  41. CountryList.Add(new Country() { CountryName = "Canada" });
  42. CountryList.Add(new Country() { CountryName = "Costa Rica" });
  43. CountryList.Add(new Country() { CountryName = "Denmark" });
  44. CountryList.Add(new Country() { CountryName = "Egypt" });
  45. CountryList.Add(new Country() { CountryName = "Ethiopia" });
  46. CountryList.Add(new Country() { CountryName = "Finland" });
  47. CountryList.Add(new Country() { CountryName = "France" });
  48. CountryList.Add(new Country() { CountryName = "Germany" });
  49. CountryList.Add(new Country() { CountryName = "Greece" });
  50. CountryList.Add(new Country() { CountryName = "Hungary" });
  51. CountryList.Add(new Country() { CountryName = "Iceland" });
  52. CountryList.Add(new Country() { CountryName = "India" });
  53. CountryList.Add(new Country() { CountryName = "Ireland" });
  54. CountryList.Add(new Country() { CountryName = "Italy" });
  55. CountryList.Add(new Country() { CountryName = "Japan" });
  56. CountryList.Add(new Country() { CountryName = "Kenya" });
  57. CountryList.Add(new Country() { CountryName = "Luxembourg" });
  58. CountryList.Add(new Country() { CountryName = "Malaysia" });
  59. CountryList.Add(new Country() { CountryName = "Netherlands" });
  60. CountryList.Add(new Country() { CountryName = "New Zealand" });
  61. CountryList.Add(new Country() { CountryName = "Oman" });
  62. CountryList.Add(new Country() { CountryName = "Pakistan" });
  63. CountryList.Add(new Country() { CountryName = "Qatar" });
  64. CountryList.Add(new Country() { CountryName = "Russia" });
  65. CountryList.Add(new Country() { CountryName = "Singapore" });
  66. CountryList.Add(new Country() { CountryName = "South Africa" });
  67. CountryList.Add(new Country() { CountryName = "Thailand" });
  68. CountryList.Add(new Country() { CountryName = "United Kingdom (UK)" });
  69. CountryList.Add(new Country() { CountryName = "United States of America (USA)" });
  70. CountryList.Add(new Country() { CountryName = "Vietnam" });
  71. CountryList.Add(new Country() { CountryName = "Yemen" });
  72. CountryList.Add(new Country() { CountryName = "Zimbabwe" });
  73. CountryJumplist countryJumpList = new CountryJumplist(CountryList);
  74. lstAlphaGroupHeader.ItemsSource = countryJumpList.Collection.View;
  75. grdAlphaJumpListPicker.ItemsSource = countryJumpList.Collection.View.CollectionGroups;
  76. }
  77. }
  78. public class CountryJumplist
  79. {
  80. private ObservableCollection<Country> loadedCountry = new ObservableCollection<Country>();
  81. public CountryJumplist(object country)
  82. {
  83. this.loadedCountry = country as ObservableCollection<Country>;
  84. }
  85. private IList data;
  86. public IList Data
  87. {
  88. get
  89. {
  90. if (this.data == null)
  91. {
  92. var items = this.loadedCountry;
  93. this.data = items.ToAlphaGroups(x => x.CountryName);
  94. }
  95. return this.data;
  96. }
  97. }
  98. private CollectionViewSource collection;
  99. public CollectionViewSource Collection
  100. {
  101. get
  102. {
  103. if (this.collection == null)
  104. {
  105. this.collection = new CollectionViewSource();
  106. this.collection.Source = this.Data;
  107. this.collection.IsSourceGrouped = true;
  108. }
  109. return this.collection;
  110. }
  111. }
  112. }
  113. public class Country
  114. {
  115. public string CountryName { get; set; }
  116. }
  117. #region JumpList
  118. public class JumpListGroup<T> : List<object>
  119. {
  120. public object Key { get; set; }
  121. public new IEnumerator<object> GetEnumerator()
  122. {
  123. return (System.Collections.Generic.IEnumerator<object>)base.GetEnumerator();
  124. }
  125. }
  126. public static class JumpListHelper
  127. {
  128. public static List<JumpListGroup<TSource>> ToAlphaGroups<TSource>(
  129. this IEnumerable<TSource> source, Func<TSource, string> selector)
  130. {
  131. var characterGroupings = new CharacterGroupings();
  132. var keys = characterGroupings.Where(x => x.Label.Any())
  133. .Select(x => x.Label)
  134. .ToDictionary(x => x);
  135. keys["..."] = "\uD83C\uDF10";
  136. var groupDictionary = keys.Select(x => new JumpListGroup<TSource>() { Key = x.Value })
  137. .ToDictionary(x => (string)x.Key);
  138. var query = from item in source
  139. orderby selector(item)
  140. select item;
  141. foreach (var item in query)
  142. {
  143. var sortValue = selector(item);
  144. groupDictionary[keys[characterGroupings.Lookup(sortValue)]].Add(item);
  145. }
  146. return groupDictionary.Select(x => x.Value).ToList();
  147. }
  148. }
  149. #endregion JumpList
  150. }
Your MainPage.xaml page looks like:
  1. <Page
  2. x:Class="SemanticZoomSample.MainPage"
  3. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5. xmlns:local="using:SemanticZoomSample"
  6. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  7. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  8. mc:Ignorable="d">
  9. <Page.Resources>
  10. <JumpListItemBackgroundConverter x:Key="JumpListItemBackgroundConverter" />
  11. <JumpListItemForegroundConverter x:Key="JumpListItemForegroundConverter" />
  12. <!--DATA TEMPLATES-->
  13. <DataTemplate x:Key="AlphaGroupHeaderTemplate">
  14. <TextBlock Text="{Binding Key}"
  15. Foreground="{ThemeResource SystemControlBackgroundAccentBrush}"
  16. FontSize="32"
  17. FontFamily="{StaticResource PhoneFontFamilySemiLight}"
  18. FontWeight="Medium"
  19. HorizontalAlignment="Left"
  20. VerticalAlignment="Bottom"
  21. Margin="5.5,0,0,9.5" />
  22. </DataTemplate>
  23. <DataTemplate x:Key="AlphaJumpListPickerItemTemplate">
  24. <Border Background ="Transparent"
  25. BorderThickness="0"
  26. Height="60"
  27. Width="60"
  28. HorizontalAlignment="Center"
  29. Margin="0,0,1.5,1.5">
  30. <TextBlock Text="{Binding Group.Key}"
  31. Foreground="{Binding Converter={StaticResource JumpListItemBackgroundConverter}}"
  32. FontSize="22"
  33. FontWeight="SemiBold"
  34. HorizontalAlignment="Center"
  35. VerticalAlignment="Center"
  36. Margin="1.5,0,0,1.5" />
  37. </Border>
  38. </DataTemplate>
  39. <!--Remove header seperator line in listView groupStyle -->
  40. <Style TargetType="ListViewHeaderItem">
  41. <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
  42. <Setter Property="FontSize" Value="{ThemeResource ListViewHeaderItemThemeFontSize}" />
  43. <Setter Property="Background" Value="Transparent" />
  44. <Setter Property="Margin" Value="0,0,0,0"/>
  45. <Setter Property="Padding" Value="6,8,12,0"/>
  46. <Setter Property="HorizontalContentAlignment" Value="Left" />
  47. <Setter Property="VerticalContentAlignment" Value="Bottom" />
  48. <Setter Property="MinHeight" Value="{ThemeResource ListViewHeaderItemMinHeight}"/>
  49. <Setter Property="UseSystemFocusVisuals" Value="True" />
  50. <Setter Property="Template">
  51. <Setter.Value>
  52. <ControlTemplate TargetType="ListViewHeaderItem">
  53. <StackPanel Background="{TemplateBinding Background}"
  54. BorderBrush="{TemplateBinding BorderBrush}"
  55. BorderThickness="{TemplateBinding BorderThickness}">
  56. <ContentPresenter x:Name="ContentPresenter"
  57. Margin="{TemplateBinding Padding}"
  58. Content="{TemplateBinding Content}"
  59. ContentTemplate="{TemplateBinding ContentTemplate}"
  60. ContentTransitions="{TemplateBinding ContentTransitions}"
  61. HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
  62. VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
  63. </StackPanel>
  64. </ControlTemplate>
  65. </Setter.Value>
  66. </Setter>
  67. </Style>
  68. </Page.Resources>
  69. <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  70. <SemanticZoom HorizontalContentAlignment="Stretch"
  71. HorizontalAlignment="Stretch">
  72. <SemanticZoom.ZoomedInView>
  73. <ListView x:Name="lstAlphaGroupHeader"
  74. ItemsSource="{Binding CountryCollectionView}"
  75. SelectionMode="Single"
  76. HorizontalContentAlignment="Stretch">
  77. <ListView.GroupStyle>
  78. <GroupStyle HeaderTemplate="{StaticResource AlphaGroupHeaderTemplate}"
  79. HidesIfEmpty="True" />
  80. </ListView.GroupStyle>
  81. <ListView.ItemTemplate>
  82. <DataTemplate>
  83. <TextBlock Text="{Binding CountryName}"/>
  84. </DataTemplate>
  85. </ListView.ItemTemplate>
  86. </ListView>
  87. </SemanticZoom.ZoomedInView>
  88. <SemanticZoom.ZoomedOutView>
  89. <GridView x:Name="grdAlphaJumpListPicker"
  90. ItemsSource="{Binding CountryCollectionViewCollectionGroups}"
  91. HorizontalAlignment="Center"
  92. HorizontalContentAlignment="Stretch"
  93. VerticalAlignment="Center"
  94. ItemTemplate="{StaticResource AlphaJumpListPickerItemTemplate}">
  95. </GridView>
  96. </SemanticZoom.ZoomedOutView>
  97. </SemanticZoom>
  98. </Grid>
  99. </Page>
Click run button to see zoom in the view.
Click group header to see zoom out view.
If you have any queries, feel free to ask.