介紹
重新想象 Windows 8 Store Apps 之 SemanticZoom
演示 SemanticZoom 的應用
通過 ISemanticZoomInformation 接口實現自定義 SemanticZoom 的 View
示例
1、演示 SemanticZoom 的應用
Index.xaml
<Page x:Class="XamlDemo.Index" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <SemanticZoom x:Name="semanticZoom" HorizontalAlignment="Left"> <!-- 放大後的視圖,詳細數據 --> <SemanticZoom.ZoomedInView> <GridView x:Name="gridViewDetails" SelectionMode="None" IsSwipeEnabled="false" Padding="120 0 0 0"> <!--分組後,details 的數據模板--> <GridView.ItemTemplate> <DataTemplate> <Grid Background="#022a56" Width="200" Height="65" Tapped="Grid_Tapped_1" Tag="{Binding}"> <TextBlock TextWrapping="Wrap" FontSize="14.667" Foreground="#ffffff" Padding="5 0" HorizontalAlignment="Left" VerticalAlignment="Center" Text="{Binding Title}"/> </Grid> </DataTemplate> </GridView.ItemTemplate> <!--分組的樣式--> <GridView.GroupStyle> <GroupStyle> <!--分組後,header 的數據模板--> <GroupStyle.HeaderTemplate> <DataTemplate> <TextBlock Text="{Binding Title}" FontSize="26.67" Height="30" Margin="0 0 0 20" /> </DataTemplate> </GroupStyle.HeaderTemplate> <!--分組後,每組數據(包括 header 和 details)的樣式--> <GroupStyle.ContainerStyle> <Style TargetType="GroupItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="GroupItem"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Margin="{TemplateBinding Padding}"/> <!-- 每組數據的 details 數據源來自 ICollectionViewGroup.GroupItems --> <ItemsControl x:Name="ItemsControl" ItemsSource="{Binding GroupItems}" Grid.Row="1"/> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </GroupStyle.ContainerStyle> <!--分組後,每組數據(包括 header 和 details)的 panel--> <GroupStyle.Panel> <ItemsPanelTemplate> <VariableSizedWrapGrid Orientation="Vertical" Margin="0 0 50 0" ItemHeight="75" Loaded="VariableSizedWrapGrid_Loaded_1" /> </ItemsPanelTemplate> </GroupStyle.Panel> </GroupStyle> </GridView.GroupStyle> <!--整體數據(一組數據算一個元素)的 panel--> <GridView.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </GridView.ItemsPanel> </GridView> </SemanticZoom.ZoomedInView> <!-- 縮小後的視圖,概述數據 --> <SemanticZoom.ZoomedOutView> <GridView Name="gridViewSummary" HorizontalAlignment="Left" Padding="120 0 0 0"> <GridView.ItemTemplate> <DataTemplate> <Grid Background="#022a56" Width="100" Height="100"> <!-- 每組數據的 header 數據源來自 ICollectionViewGroup.Group --> <TextBlock Text="{Binding Group.Title}" Foreground="#ffffff" Opacity="0.9" FontSize="14.667" Margin="5" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" /> </Grid> </DataTemplate> </GridView.ItemTemplate> <GridView.ItemsPanel> <ItemsPanelTemplate> <WrapGrid MaximumRowsOrColumns="8" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal" /> </ItemsPanelTemplate> </GridView.ItemsPanel> <GridView.ItemContainerStyle> <Style TargetType="GridViewItem"> <Setter Property="Margin" Value="5 5 5 30" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> </Style> </GridView.ItemContainerStyle> </GridView> </SemanticZoom.ZoomedOutView> </SemanticZoom> </Grid> </Page>
Index.xaml.cs
/* * 本頁為此 app 的導航頁,同時用於演示: * 1、ItemsControl 控件如何分組 * 2、SemanticZoom 控件的應用 * * * SemanticZoom - 用於關聯兩個有語義關系的視圖 * ZoomedInView - 放大後的視圖,詳細數據 * ZoomedOutView - 縮小後的視圖,概述數據 * IsZoomedInViewActive - ZoomedInView 是否為當前正在顯示的視圖 * CanChangeViews - 是否可在兩個視圖間切換 * IsZoomOutButtonEnabled - 是否顯示用於切換視圖的按鈕 * ToggleActiveView() - 切換視圖 * ViewChangeStarted - 視圖開始切換時觸發的事件 * ViewChangeCompleted - 視圖切換完成時觸發的事件 * * * ItemsControl - 一個用於呈現集合數據的控件(GridView, ListView, FlipView, ListBox 等均直接或間接地繼承了 ItemsControl) * ItemsControl 控件提供了分組功能 * * CollectionViewSource - 對集合數據啟用分組支持 * Source - 數據源 * View - 獲取視圖對象,返回一個實現了 ICollectionView 接口的對象 * IsSourceGrouped - 數據源是否是一個被分組的數據 * ItemsPath - 數據源中,子數據集合的屬性名稱 * * ICollectionView - 支持數據分組 * CollectionGroups - 組數據集合 */ using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Navigation; using XamlDemo.Common; namespace XamlDemo { public sealed partial class Index : Page { // 本頁所用到的 GridView 的水平方向上的滾動值 private double _scrollViewerHorizontalOffset = 0; public Index() { this.InitializeComponent(); XElement root = XElement.Load("SiteMap.xml"); var items = LoadData(root); // 構造數據源 CollectionViewSource groupedNavigationData = new CollectionViewSource(); groupedNavigationData.IsSourceGrouped = true; groupedNavigationData.Source = items; groupedNavigationData.ItemsPath = new PropertyPath("Items"); // 綁定數據 gridViewDetails.ItemsSource = groupedNavigationData.View; // 全部數據 gridViewSummary.ItemsSource = groupedNavigationData.View.CollectionGroups; // 關聯的組數據集合 // 必須緩存此頁 this.NavigationCacheMode = NavigationCacheMode.Required; gridViewDetails.Loaded += gridViewDetails_Loaded; } // 導航到其它頁之前,保存本頁所用到的 GridView 的水平方向上的滾動值 protected override void OnNavigatedFrom(NavigationEventArgs e) { var scrollViewer = Helper.GetVisualChild<ScrollViewer>(gridViewDetails); _scrollViewerHorizontalOffset = scrollViewer.HorizontalOffset; } // GridView 加載之後,指定其水平方向上的滾動值 void gridViewDetails_Loaded(object sender, RoutedEventArgs e) { var scrollViewer = Helper.GetVisualChild<ScrollViewer>(gridViewDetails); scrollViewer.ScrollToHorizontalOffset(_scrollViewerHorizontalOffset); } // 獲取數據 private List<NavigationModel> LoadData(XElement root) { if (root == null) return null; var items = from n in root.Elements("node") select new NavigationModel { Title = (string)n.Attribute("title"), Url = (string)n.Attribute("url"), Items = LoadData(n) }; return items.ToList(); } // 導航到指定的 Demo 頁 private void Grid_Tapped_1(object sender, TappedRoutedEventArgs e) { var model = (NavigationModel)(sender as Grid).Tag; MainPage.Current.SubTitle = model.Title; MainPage.Current.Container.Navigate(Type.GetType(model.Url)); } // 根據屏幕的 height 調整 VariableSizedWrapGrid 的 MaximumRowsOrColumns // 本例會自動 wrap ,所以不需要以下邏輯,在需要的場景下可以用之 private void VariableSizedWrapGrid_Loaded_1(object sender, RoutedEventArgs e) { /* var screenHeight = Window.Current.Bounds.Height; // CoreWindow.GetForCurrentThread().Bounds.Height var vswg = sender as VariableSizedWrapGrid; vswg.MaximumRowsOrColumns = (int)((screenHeight - 200) / 75); */ } class NavigationModel { public string Title { get; set; } public string Url { get; set; } public List<NavigationModel> Items { get; set; } } } }
2、演示如何自定義 SemanticZoom 視圖
SemanticZoom/MyFlipView.cs
/* * 開發一個實現了 ISemanticZoomInformation 接口的自定義 FlipView */ using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Data; namespace XamlDemo.Controls.SemanticZoom { public class MyFlipView : FlipView, ISemanticZoomInformation { public MyFlipView() : base() { } public void CompleteViewChange() { } public void CompleteViewChangeFrom(SemanticZoomLocation source, SemanticZoomLocation destination) { } public void CompleteViewChangeTo(SemanticZoomLocation source, SemanticZoomLocation destination) { } public void InitializeViewChange() { } public bool IsActiveView { get; set; } public bool IsZoomedInView { get; set; } public Windows.UI.Xaml.Controls.SemanticZoom SemanticZoomOwner { get; set; } public void StartViewChangeFrom(SemanticZoomLocation source, SemanticZoomLocation destination) { } /// <summary> /// ZoomedOutView -> ZoomedInView 時觸發的事件 /// </summary> /// <param name="source">在 ZoomedOutView 時被選中的數據</param> /// <param name="destination">需要傳遞給 ZoomedInView 的數據</param> public void StartViewChangeTo(SemanticZoomLocation source, SemanticZoomLocation destination) { /* * 注: * GridView 和 ListView 均實現了 ISemanticZoomInformation 接口 * 參見本 app 的關於 SemanticZoom 的 Demo,通過 CollectionViewSource 綁定數據即可使 SemanticZoom 中的兩個視圖進行有關聯地切換 * 此時此處的 source.Item 便為一個 ICollectionViewGroup 類型的數據,其有兩個屬性:Group 和 GroupItems */ // 獲取在 ZoomedOutView 中被選中的項,即被選中的父親 NavigationModel model = source.Item as NavigationModel; // 將此父親的所有子數據傳遞給 ZoomedInView,接下來會執行 MakeVisible() 方法 destination.Item = model.Items; } /// <summary> /// 開始 ZoomedOutView -> ZoomedInView 之後,會調用此方法 /// 一般在此處重整 ZoomedInView 的數據源,或者滾動 ZoomedInView 中的內容到指定的項以對應 ZoomedOutView 中被選中的數據 /// </summary> /// <param name="item">由 StartViewChangeTo() 方法傳遞給 ZoomedInView 的數據 </param> public void MakeVisible(SemanticZoomLocation item) { // 將 FlipView 的數據源指定為被選中的父親的所有子數據 this.ItemsSource = item.Item; } } }
SemanticZoom/CustomView.xaml
<Page x:Class="XamlDemo.Controls.SemanticZoom.CustomView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Controls.SemanticZoom" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <SemanticZoom x:Name="semanticZoom" IsZoomedInViewActive="False" Margin="120 0 0 0"> <!-- 放大後的視圖,詳細數據 --> <SemanticZoom.ZoomedInView> <local:MyFlipView x:Name="flipView" Width="600" Height="300" HorizontalAlignment="Left"> <FlipView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Title}" FontSize="26.667" /> </DataTemplate> </FlipView.ItemTemplate> <FlipView.ItemContainerStyle> <Style TargetType="FlipViewItem"> <Setter Property="Background" Value="Blue" /> </Style> </FlipView.ItemContainerStyle> </local:MyFlipView> </SemanticZoom.ZoomedInView> <!-- 縮小後的視圖,概述數據 --> <SemanticZoom.ZoomedOutView> <GridView Name="gridView" HorizontalAlignment="Left"> <GridView.ItemTemplate> <DataTemplate> <Grid Background="#022a56" Width="100" Height="100"> <TextBlock Text="{Binding Title}" Foreground="#ffffff" Opacity="0.9" FontSize="14.667" Margin="5" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap" /> </Grid> </DataTemplate> </GridView.ItemTemplate> <GridView.ItemsPanel> <ItemsPanelTemplate> <WrapGrid MaximumRowsOrColumns="8" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal" /> </ItemsPanelTemplate> </GridView.ItemsPanel> <GridView.ItemContainerStyle> <Style TargetType="GridViewItem"> <Setter Property="Margin" Value="5 5 5 30" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" /> </Style> </GridView.ItemContainerStyle> </GridView> </SemanticZoom.ZoomedOutView> </SemanticZoom> </Grid> </Page>
SemanticZoom/CustomView.xaml.cs
/* * 演示如何自定義 SemanticZoom 視圖 * 演示步驟: * 1、在 ZoomedOutView 視圖中的 GridView 中選中某一項 * 2、展開 ZoomedInView 視圖後,其內的 FlipView 顯示之前被選中項的所有子數據(需要開發一個實現了 ISemanticZoomInformation 接口的自定義 FlipView,參見 MyFlipView.cs) * * 注: * GridView 和 ListView 均實現了 ISemanticZoomInformation 接口,所以可以在 SemanticZoom 的兩個視 圖間有關聯地切換 * 要讓其它控件也實現類似的功能,就必須使其實現 ISemanticZoomInformation 接口 */ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using Windows.UI.Xaml.Controls; namespace XamlDemo.Controls.SemanticZoom { public sealed partial class CustomView : Page { public CustomView() { this.InitializeComponent(); XElement root = XElement.Load("SiteMap.xml"); var items = LoadData(root); // 綁定數據 gridView.ItemsSource = items; } // 獲取數據 private List<NavigationModel> LoadData(XElement root) { if (root == null) return null; var items = from n in root.Elements("node") select new NavigationModel { Title = (string)n.Attribute("title"), Url = (string)n.Attribute("url"), Items = LoadData(n) }; return items.ToList(); } } public class NavigationModel { public string Title { get; set; } public string Url { get; set; } public List<NavigationModel> Items { get; set; } } }
OK
[源碼下載]:http://files.cnblogs.com/webabcd/Windows8.rar